use video stc for display. make skipping look a bit better.
[enigma2.git] / 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/sec.h>
6
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
16
17 DEFINE_REF(eDVBAllocatedFrontend);
18
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
20 {
21         m_fe->inc_use();
22 }
23
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
25 {
26         m_fe->dec_use();
27 }
28
29 DEFINE_REF(eDVBAllocatedDemux);
30
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
32 {
33         m_demux->m_inuse++;
34 }
35
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
37 {
38         --m_demux->m_inuse;
39 }
40
41 DEFINE_REF(eDVBResourceManager);
42
43 eDVBResourceManager *eDVBResourceManager::instance;
44
45 eDVBResourceManager::eDVBResourceManager()
46 {
47         avail = 1;
48         busy = 0;
49         m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
50         if (!instance)
51                 instance = this;
52                 
53                 /* search available adapters... */
54
55                 // add linux devices
56         
57         int num_adapter = 0;
58         while (eDVBAdapterLinux::exist(num_adapter))
59         {
60                 addAdapter(new eDVBAdapterLinux(num_adapter));
61                 num_adapter++;
62         }
63         
64         eDebug("found %d adapter, %d frontends and %d demux", 
65                 m_adapter.size(), m_frontend.size(), m_demux.size());
66 }
67
68
69 DEFINE_REF(eDVBAdapterLinux);
70 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
71 {
72                 // scan frontends
73         int num_fe = 0;
74         
75         eDebug("scanning for frontends..");
76         while (1)
77         {
78                 struct stat s;
79                 char filename[128];
80 #if HAVE_DVB_API_VERSION < 3
81                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
82 #else
83                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
84 #endif
85                 if (stat(filename, &s))
86                         break;
87                 ePtr<eDVBFrontend> fe;
88
89                 int ok = 0;
90                 fe = new eDVBFrontend(m_nr, num_fe, ok);
91                 if (ok)
92                         m_frontend.push_back(fe);
93                 ++num_fe;
94         }
95         
96                 // scan demux
97         int num_demux = 0;
98         while (1)
99         {
100                 struct stat s;
101                 char filename[128];
102 #if HAVE_DVB_API_VERSION < 3
103                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
104 #else
105                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
106 #endif
107                 if (stat(filename, &s))
108                         break;
109                 ePtr<eDVBDemux> demux;
110                 
111                 demux = new eDVBDemux(m_nr, num_demux);
112                 m_demux.push_back(demux);
113                         
114                 ++num_demux;
115         }
116 }
117
118 int eDVBAdapterLinux::getNumDemux()
119 {
120         return m_demux.size();
121 }
122
123 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
124 {
125         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
126         while (nr && (i != m_demux.end()))
127         {
128                 --nr;
129                 ++i;
130         }
131         
132         if (i != m_demux.end())
133                 demux = *i;
134         else
135                 return -1;
136                 
137         return 0;
138 }
139
140 int eDVBAdapterLinux::getNumFrontends()
141 {
142         return m_frontend.size();
143 }
144
145 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
146 {
147         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
148         while (nr && (i != m_frontend.end()))
149         {
150                 --nr;
151                 ++i;
152         }
153         
154         if (i != m_frontend.end())
155                 fe = *i;
156         else
157                 return -1;
158                 
159         return 0;
160 }
161
162 int eDVBAdapterLinux::exist(int nr)
163 {
164         struct stat s;
165         char filename[128];
166 #if HAVE_DVB_API_VERSION < 3
167         sprintf(filename, "/dev/dvb/card%d", nr);
168 #else
169         sprintf(filename, "/dev/dvb/adapter%d", nr);
170 #endif
171         if (!stat(filename, &s))
172                 return 1;
173         return 0;
174 }
175
176 eDVBResourceManager::~eDVBResourceManager()
177 {
178         if (instance == this)
179                 instance = 0;
180 }
181
182 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
183 {
184         int num_fe = adapter->getNumFrontends();
185         int num_demux = adapter->getNumDemux();
186         
187         m_adapter.push_back(adapter);
188         
189         int i;
190         for (i=0; i<num_demux; ++i)
191         {
192                 ePtr<eDVBDemux> demux;
193                 if (!adapter->getDemux(demux, i))
194                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
195         }
196
197         for (i=0; i<num_fe; ++i)
198         {
199                 ePtr<eDVBFrontend> frontend;
200
201                 if (!adapter->getFrontend(frontend, i))
202                 {
203                         frontend->setSEC(m_sec);
204                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
205                 }
206         }
207 }
208
209 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
210 {
211         ePtr<eDVBRegisteredFrontend> best;
212         int bestval = 0;
213
214         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
215                 if (!i->m_inuse)
216                 {
217                         int c = i->m_frontend->isCompatibleWith(feparm);
218                         if (c > bestval)
219                         {
220                                 bestval = c;
221                                 best = i;
222                         }
223                 }
224
225         if (best)
226         {
227                 fe = new eDVBAllocatedFrontend(best);
228                 return 0;
229         }
230         
231         fe = 0;
232         
233         return -1;
234 }
235
236 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
237 {
238         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
239                 if ((!nr) && !i->m_inuse)
240                 {
241                         fe = new eDVBAllocatedFrontend(i);
242                         return 0;
243                 }
244         
245         fe = 0;
246         return -1;
247 }
248
249 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
250 {
251                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
252                    never use the first one unless we need a decoding demux. */
253
254         eDebug("allocate demux");
255         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
256         
257         if (i == m_demux.end())
258                 return -1;
259                 
260         int n=0;
261                 /* FIXME: hardware demux policy */
262         if (!(cap & iDVBChannel::capDecode))
263                 ++i, ++n;
264         
265         for (; i != m_demux.end(); ++i, ++n)
266                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
267                 {
268                         if ((cap & iDVBChannel::capDecode) && n)
269                                 continue;
270                         
271                         demux = new eDVBAllocatedDemux(i);
272                         if (fe)
273                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
274                         else
275                                 demux->get().setSourcePVR(0);
276                         return 0;
277                 }
278         eDebug("demux not found");
279         return -1;
280 }
281
282 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
283 {
284         m_list = list;
285         return 0;
286 }
287
288 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
289 {
290         list = m_list;
291         if (list)
292                 return 0;
293         else
294                 return -ENOENT;
295 }
296
297 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
298 {
299                 /* first, check if a channel is already existing. */
300
301         if (m_cached_channel)
302         {
303                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
304                 if(channelid==cache_chan->getChannelID())
305                 {
306                         eDebug("use cached_channel");
307                         channel=m_cached_channel;
308                         return 0;
309                 }
310                 m_cached_channel=0;
311         }
312
313 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
314         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
315         {
316 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
317                 if (i->m_channel_id == channelid)
318                 {
319 //                      eDebug("found shared channel..");
320                         channel = i->m_channel;
321                         return 0;
322                 }
323         }
324         
325         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
326
327         if (!m_list)
328         {
329                 eDebug("no channel list set!");
330                 return -ENOENT;
331         }
332
333         ePtr<iDVBFrontendParameters> feparm;
334         if (m_list->getChannelFrontendData(channelid, feparm))
335         {
336                 eDebug("channel not found!");
337                 return -ENOENT;
338         }
339
340         /* allocate a frontend. */
341         
342         ePtr<eDVBAllocatedFrontend> fe;
343         
344         if (allocateFrontend(fe, feparm))
345                 return errNoFrontend;
346
347         RESULT res;
348         ePtr<eDVBChannel> ch;
349         ch = new eDVBChannel(this, fe);
350
351         res = ch->setChannel(channelid, feparm);
352         if (res)
353         {
354                 channel = 0;
355                 return errChidNotFound;
356         }
357         m_cached_channel = channel = ch;
358
359         return 0;
360 }
361
362 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
363 {
364         ePtr<eDVBAllocatedFrontend> fe;
365
366         if (m_cached_channel)
367                 m_cached_channel=0;
368
369         if (allocateFrontendByIndex(fe, frontend_index))
370                 return errNoFrontend;
371         
372         eDVBChannel *ch;
373         ch = new eDVBChannel(this, fe);
374
375         channel = ch;
376         return 0;
377 }
378
379
380 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
381 {
382         ePtr<eDVBAllocatedDemux> demux;
383
384         if (m_cached_channel)
385                 m_cached_channel=0;
386
387         eDVBChannel *ch;
388         ch = new eDVBChannel(this, 0);
389         
390         channel = ch;
391         return 0;
392 }
393
394 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
395 {
396         m_active_channels.push_back(active_channel(chid, ch));
397         /* emit */ m_channelAdded(ch);
398         return 0;
399 }
400
401 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
402 {
403         int cnt = 0;
404         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
405         {
406                 if (i->m_channel == ch)
407                 {
408                         i = m_active_channels.erase(i);
409                         ++cnt;
410                 } else
411                         ++i;
412         }
413         ASSERT(cnt == 1);
414         if (cnt == 1)
415                 return 0;
416         return -ENOENT;
417 }
418
419 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
420 {
421         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
422         return 0;
423 }
424
425 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
426 {
427         ePtr<eDVBRegisteredFrontend> best;
428         int bestval = 0;
429
430         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
431                 if (!i->m_inuse)
432                 {
433                         int c = i->m_frontend->isCompatibleWith(feparm);
434                         if (c > bestval)
435                                 bestval = c;
436                 }
437
438         return bestval>0;
439 }
440
441 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
442 {
443                 /* first, check if a channel is already existing. */
444 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
445         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
446         {
447 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
448                 if (i->m_channel_id == channelid)
449                 {
450 //                      eDebug("found shared channel..");
451                         return true;
452                 }
453         }
454
455         int *decremented_fe_usecount=NULL;
456
457         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
458         {
459 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
460                 if (i->m_channel_id == ignore)
461                 {
462                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
463                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1)  // channel only used once..
464                         {
465                                 ePtr<iDVBFrontend> fe;
466                                 if (!i->m_channel->getFrontend(fe))
467                                 {
468                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
469                                         {
470                                                 if ( &(*fe) == &(*ii->m_frontend) )
471                                                 {
472                                                         --ii->m_inuse;
473                                                         decremented_fe_usecount = &ii->m_inuse;
474                                                         break;
475                                                 }
476                                         }
477                                 }
478                         }
479                         break;
480                 }
481         }
482
483         if (!m_list)
484         {
485                 eDebug("no channel list set!");
486                 return false;
487         }
488
489         ePtr<iDVBFrontendParameters> feparm;
490         if (m_list->getChannelFrontendData(channelid, feparm))
491         {
492                 eDebug("channel not found!");
493                 return false;
494         }
495
496         bool ret = canAllocateFrontend(feparm);
497
498         if (decremented_fe_usecount)
499                 ++(*decremented_fe_usecount);
500
501         return ret;
502 }
503
504 DEFINE_REF(eDVBChannel);
505
506 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
507 {
508         m_frontend = frontend;
509
510         m_pvr_thread = 0;
511         
512         if (m_frontend)
513                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
514 }
515
516 eDVBChannel::~eDVBChannel()
517 {
518         if (m_channel_id)
519                 m_mgr->removeChannel(this);
520         
521         if (m_pvr_thread)
522         {
523                 m_pvr_thread->stop();
524                 ::close(m_pvr_fd_src);
525                 ::close(m_pvr_fd_dst);
526                 delete m_pvr_thread;
527         }
528 }
529
530 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
531 {
532         int state, ourstate = 0;
533         
534                 /* if we are already in shutdown, don't change state. */
535         if (m_state == state_release)
536                 return;
537         
538         if (fe->getState(state))
539                 return;
540         
541         if (state == iDVBFrontend::stateLock)
542         {
543                 eDebug("OURSTATE: ok");
544                 ourstate = state_ok;
545         } else if (state == iDVBFrontend::stateTuning)
546         {
547                 eDebug("OURSTATE: tuning");
548                 ourstate = state_tuning;
549         } else if (state == iDVBFrontend::stateLostLock)
550         {
551                 eDebug("OURSTATE: lost lock");
552                 ourstate = state_unavailable;
553         } else if (state == iDVBFrontend::stateFailed)
554         {
555                 eDebug("OURSTATE: failed");
556                 ourstate = state_failed;
557         } else
558                 eFatal("state unknown");
559         
560         if (ourstate != m_state)
561         {
562                 m_state = ourstate;
563                 m_stateChanged(this);
564         }
565 }
566
567 void eDVBChannel::AddUse()
568 {
569         ++m_use_count;
570 }
571
572 void eDVBChannel::ReleaseUse()
573 {
574         if (!--m_use_count)
575         {
576                 m_state = state_release;
577                 m_stateChanged(this);
578         }
579 }
580
581 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
582 {
583         if (m_channel_id)
584                 m_mgr->removeChannel(this);
585                 
586         if (!channelid)
587                 return 0;
588
589         if (!m_frontend)
590         {
591                 eDebug("no frontend to tune!");
592                 return -ENODEV;
593         }
594         
595         m_channel_id = channelid;
596         m_mgr->addChannel(channelid, this);
597         m_state = state_tuning;
598                         /* if tuning fails, shutdown the channel immediately. */
599         int res;
600         res = m_frontend->get().tune(*feparm);
601         
602         if (res)
603         {
604                 m_state = state_release;
605                 m_stateChanged(this);
606                 return res;
607         }
608         
609         return 0;
610 }
611
612 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
613 {
614         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
615         return 0;
616 }
617
618 RESULT eDVBChannel::getState(int &state)
619 {
620         state = m_state;
621         return 0;
622 }
623
624 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
625 {
626         return -1;
627 }
628
629 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
630 {
631         eDebug("get %d demux", cap);
632         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
633         
634         if (!our_demux)
635         {
636                 demux = 0;
637                 
638                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
639                         return -1;
640                 
641         }
642         
643         demux = *our_demux;
644         if (cap & capDecode)
645         {
646                 our_demux = 0;
647         }
648         return 0;
649 }
650
651 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
652 {
653         frontend = &m_frontend->get();
654         if (frontend)
655                 return 0;
656         else
657                 return -ENODEV;
658 }
659
660 RESULT eDVBChannel::playFile(const char *file)
661 {
662         ASSERT(!m_frontend);
663         if (m_pvr_thread)
664         {
665                 m_pvr_thread->stop();
666                 delete m_pvr_thread;
667                 m_pvr_thread = 0;
668         }
669         
670         m_tstools.openFile(file);
671         
672                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
673                    THEN DO A REAL FIX HERE! */
674         
675                 /* (this codepath needs to be improved anyway.) */
676         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
677         if (m_pvr_fd_dst < 0)
678         {
679                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
680                 return -ENODEV;
681         }
682         
683         m_pvr_fd_src = open(file, O_RDONLY);
684         if (m_pvr_fd_src < 0)
685         {
686                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
687                 close(m_pvr_fd_dst);
688                 return -ENOENT;
689         }
690         
691         m_state = state_ok;
692         m_stateChanged(this);
693         
694         m_pvr_thread = new eFilePushThread();
695         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
696
697         return 0;
698 }
699
700 RESULT eDVBChannel::getLength(pts_t &len)
701 {
702         return m_tstools.calcLen(len);
703 }
704
705 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
706 {
707         if (!decoding_demux)
708                 return -1;
709         
710         off_t begin = 0;
711                 /* getPTS for offset 0 is cached, so it doesn't harm. */
712         int r = m_tstools.getPTS(begin, pos);
713         if (r)
714         {
715                 eDebug("tstools getpts(0) failed!");
716                 return r;
717         }
718         
719         pts_t now;
720         
721                         /* TODO: this is a gross hack. */
722         r = decoding_demux->getSTC(now, mode ? 128 : 0);
723
724         if (r)
725         {
726                 eDebug("demux getSTC failed");
727                 return -1;
728         }
729         
730 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
731                 /* when we are less than 10 seconds before the start, return 0. */
732                 /* (we're just waiting for the timespam to start) */
733         if ((now < pos) && ((pos - now) < 90000 * 10))
734         {
735                 pos = 0;
736                 return 0;
737         }
738         
739         if (now < pos) /* wrap around */
740                 pos = now + ((pts_t)1)<<33 - pos;
741         else
742                 pos = now - pos;
743         
744         return 0;
745 }
746
747 RESULT eDVBChannel::seekTo(iDVBDemux *decoding_demux, int relative, pts_t &pts)
748 {
749         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
750         
751         if (bitrate == -1)
752                 return -1;
753         
754         if (relative)
755         {
756                 pts_t now;
757                 if (getCurrentPosition(decoding_demux, now, 0))
758                 {
759                         eDebug("seekTo: getCurrentPosition failed!");
760                         return -1;
761                 }
762                 pts += now;
763         }
764         
765         if (pts < 0)
766                 pts = 0;
767         
768         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
769         
770         seekToPosition(decoding_demux, offset);
771         return 0;
772 }
773
774 RESULT eDVBChannel::seekToPosition(iDVBDemux *decoding_demux, const off_t &r)
775 {
776                         /* when seeking, we have to ensure that all buffers are flushed.
777                            there are basically 3 buffers:
778                            a.) the filepush's internal buffer
779                            b.) the PVR buffer (before demux)
780                            c.) the ratebuffer (after demux)
781                            
782                            it's important to clear them in the correct order, otherwise
783                            the ratebuffer (for example) would immediately refill from
784                            the not-yet-flushed PVR buffer.
785                         */
786         eDebug("eDVBChannel: seekToPosition .. %llx", r);
787         m_pvr_thread->pause();
788
789                 /* flush internal filepush buffer */
790         m_pvr_thread->flush();
791
792                 /* HACK: flush PVR buffer */
793         ::ioctl(m_pvr_fd_dst, 0);
794         
795                 /* flush ratebuffers (video, audio) */
796         if (decoding_demux)
797                 decoding_demux->flush();
798
799                 /* demux will also flush all decoder.. */
800         m_pvr_thread->seek(SEEK_SET, r);
801         m_pvr_thread->resume();
802         return 0;
803 }