remove unneeded code
[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->m_inuse++;
22 }
23
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
25 {
26         --m_fe->m_inuse;
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->setTone(iDVBFrontend::toneOff);
204                         frontend->setVoltage(iDVBFrontend::voltageOff);
205                         frontend->setSEC(m_sec);
206                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
207                 }
208         }
209 }
210
211 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
212 {
213         ePtr<eDVBRegisteredFrontend> best;
214         int bestval = 0;
215
216         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
217                 if (!i->m_inuse)
218                 {
219                         int c = i->m_frontend->isCompatibleWith(feparm);
220                         if (c > bestval)
221                         {
222                                 bestval = c;
223                                 best = i;
224                         }
225                 }
226
227         if (best)
228         {
229                 fe = new eDVBAllocatedFrontend(best);
230                 return 0;
231         }
232         
233         fe = 0;
234         
235         return -1;
236 }
237
238 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
239 {
240         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
241                 if ((!nr) && !i->m_inuse)
242                 {
243                         fe = new eDVBAllocatedFrontend(i);
244                         return 0;
245                 }
246         
247         fe = 0;
248         return -1;
249 }
250
251 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
252 {
253                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
254                    never use the first one unless we need a decoding demux. */
255
256         eDebug("allocate demux");
257         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
258         
259         if (i == m_demux.end())
260                 return -1;
261                 
262         int n=0;
263                 /* FIXME: hardware demux policy */
264         if (!(cap & iDVBChannel::capDecode))
265                 ++i, ++n;
266         
267         for (; i != m_demux.end(); ++i, ++n)
268                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
269                 {
270                         if ((cap & iDVBChannel::capDecode) && n)
271                                 continue;
272                         
273                         demux = new eDVBAllocatedDemux(i);
274                         if (fe)
275                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
276                         else
277                                 demux->get().setSourcePVR(0);
278                         return 0;
279                 }
280         eDebug("demux not found");
281         return -1;
282 }
283
284 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
285 {
286         m_list = list;
287         return 0;
288 }
289
290 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
291 {
292         list = m_list;
293         if (list)
294                 return 0;
295         else
296                 return -ENOENT;
297 }
298
299 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
300 {
301                 /* first, check if a channel is already existing. */
302
303         if (m_cached_channel)
304         {
305                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
306                 if(channelid==cache_chan->getChannelID())
307                 {
308                         eDebug("use cached_channel");
309                         channel=m_cached_channel;
310                         return 0;
311                 }
312                 m_cached_channel=0;
313         }
314
315 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
316         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
317         {
318 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
319                 if (i->m_channel_id == channelid)
320                 {
321 //                      eDebug("found shared channel..");
322                         channel = i->m_channel;
323                         return 0;
324                 }
325         }
326         
327         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
328
329         if (!m_list)
330         {
331                 eDebug("no channel list set!");
332                 return -ENOENT;
333         }
334
335         ePtr<iDVBFrontendParameters> feparm;
336         if (m_list->getChannelFrontendData(channelid, feparm))
337         {
338                 eDebug("channel not found!");
339                 return -ENOENT;
340         }
341
342         /* allocate a frontend. */
343         
344         ePtr<eDVBAllocatedFrontend> fe;
345         
346         if (allocateFrontend(fe, feparm))
347                 return errNoFrontend;
348
349         RESULT res;
350         ePtr<eDVBChannel> ch;
351         ch = new eDVBChannel(this, fe);
352
353         res = ch->setChannel(channelid, feparm);
354         if (res)
355         {
356                 channel = 0;
357                 return errChidNotFound;
358         }
359         m_cached_channel = channel = ch;
360
361         return 0;
362 }
363
364 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
365 {
366         ePtr<eDVBAllocatedFrontend> fe;
367
368         if (allocateFrontendByIndex(fe, frontend_index))
369                 return errNoFrontend;
370         
371         eDVBChannel *ch;
372         ch = new eDVBChannel(this, fe);
373
374         channel = ch;
375         return 0;
376 }
377
378
379 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
380 {
381         ePtr<eDVBAllocatedDemux> demux;
382         
383         eDVBChannel *ch;
384         ch = new eDVBChannel(this, 0);
385         
386         channel = ch;
387         return 0;
388 }
389
390 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
391 {
392         m_active_channels.push_back(active_channel(chid, ch));
393         /* emit */ m_channelAdded(ch);
394         return 0;
395 }
396
397 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
398 {
399         int cnt = 0;
400         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
401         {
402                 if (i->m_channel == ch)
403                 {
404                         i = m_active_channels.erase(i);
405                         ++cnt;
406                 } else
407                         ++i;
408         }
409         ASSERT(cnt == 1);
410         if (cnt == 1)
411                 return 0;
412         return -ENOENT;
413 }
414
415 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
416 {
417         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
418         return 0;
419 }
420
421 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
422 {
423         ePtr<eDVBRegisteredFrontend> best;
424         int bestval = 0;
425
426         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
427                 if (!i->m_inuse)
428                 {
429                         int c = i->m_frontend->isCompatibleWith(feparm);
430                         if (c > bestval)
431                                 bestval = c;
432                 }
433
434         return bestval>0;
435 }
436
437 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
438 {
439                 /* first, check if a channel is already existing. */
440 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
441         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
442         {
443 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
444                 if (i->m_channel_id == channelid)
445                 {
446 //                      eDebug("found shared channel..");
447                         return true;
448                 }
449         }
450
451         int *decremented_fe_usecount=NULL;
452
453         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
454         {
455 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
456                 if (i->m_channel_id == ignore)
457                 {
458                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
459                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1)  // channel only used once..
460                         {
461                                 ePtr<iDVBFrontend> fe;
462                                 if (!i->m_channel->getFrontend(fe))
463                                 {
464                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
465                                         {
466                                                 if ( &(*fe) == &(*ii->m_frontend) )
467                                                 {
468                                                         --ii->m_inuse;
469                                                         decremented_fe_usecount = &ii->m_inuse;
470                                                         break;
471                                                 }
472                                         }
473                                 }
474                         }
475                         break;
476                 }
477         }
478
479         if (!m_list)
480         {
481                 eDebug("no channel list set!");
482                 return false;
483         }
484
485         ePtr<iDVBFrontendParameters> feparm;
486         if (m_list->getChannelFrontendData(channelid, feparm))
487         {
488                 eDebug("channel not found!");
489                 return false;
490         }
491
492         bool ret = canAllocateFrontend(feparm);
493
494         if (decremented_fe_usecount)
495                 ++(*decremented_fe_usecount);
496
497         return ret;
498 }
499
500 DEFINE_REF(eDVBChannel);
501
502 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
503 {
504         m_frontend = frontend;
505
506         m_pvr_thread = 0;
507         
508         if (m_frontend)
509                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
510 }
511
512 eDVBChannel::~eDVBChannel()
513 {
514         if (m_channel_id)
515                 m_mgr->removeChannel(this);
516         
517         if (m_pvr_thread)
518         {
519                 m_pvr_thread->stop();
520                 ::close(m_pvr_fd_src);
521                 ::close(m_pvr_fd_dst);
522                 delete m_pvr_thread;
523         }
524 }
525
526 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
527 {
528         int state, ourstate = 0;
529         
530                 /* if we are already in shutdown, don't change state. */
531         if (m_state == state_release)
532                 return;
533         
534         if (fe->getState(state))
535                 return;
536         
537         if (state == iDVBFrontend::stateLock)
538         {
539                 eDebug("OURSTATE: ok");
540                 ourstate = state_ok;
541         } else if (state == iDVBFrontend::stateTuning)
542         {
543                 eDebug("OURSTATE: tuning");
544                 ourstate = state_tuning;
545         } else if (state == iDVBFrontend::stateLostLock)
546         {
547                 eDebug("OURSTATE: lost lock");
548                 ourstate = state_unavailable;
549         } else if (state == iDVBFrontend::stateFailed)
550         {
551                 eDebug("OURSTATE: failed");
552                 ourstate = state_failed;
553         } else
554                 eFatal("state unknown");
555         
556         if (ourstate != m_state)
557         {
558                 m_state = ourstate;
559                 m_stateChanged(this);
560         }
561 }
562
563 void eDVBChannel::AddUse()
564 {
565         ++m_use_count;
566 }
567
568 void eDVBChannel::ReleaseUse()
569 {
570         if (!--m_use_count)
571         {
572                 m_state = state_release;
573                 m_stateChanged(this);
574         }
575 }
576
577 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
578 {
579         if (m_channel_id)
580                 m_mgr->removeChannel(this);
581                 
582         if (!channelid)
583                 return 0;
584
585         if (!m_frontend)
586         {
587                 eDebug("no frontend to tune!");
588                 return -ENODEV;
589         }
590         
591         m_channel_id = channelid;
592         m_mgr->addChannel(channelid, this);
593         m_state = state_tuning;
594                         /* if tuning fails, shutdown the channel immediately. */
595         int res;
596         res = m_frontend->get().tune(*feparm);
597         
598         if (res)
599         {
600                 m_state = state_release;
601                 m_stateChanged(this);
602                 return res;
603         }
604         
605         return 0;
606 }
607
608 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
609 {
610         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
611         return 0;
612 }
613
614 RESULT eDVBChannel::getState(int &state)
615 {
616         state = m_state;
617         return 0;
618 }
619
620 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
621 {
622         return -1;
623 }
624
625 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
626 {
627         eDebug("get %d demux", cap);
628         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
629         
630         if (!our_demux)
631         {
632                 demux = 0;
633                 
634                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
635                         return -1;
636                 
637         }
638         
639         demux = *our_demux;
640         if (cap & capDecode)
641         {
642                 our_demux = 0;
643         }
644         return 0;
645 }
646
647 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
648 {
649         frontend = &m_frontend->get();
650         if (frontend)
651                 return 0;
652         else
653                 return -ENODEV;
654 }
655
656 RESULT eDVBChannel::playFile(const char *file)
657 {
658         ASSERT(!m_frontend);
659         if (m_pvr_thread)
660         {
661                 m_pvr_thread->stop();
662                 delete m_pvr_thread;
663                 m_pvr_thread = 0;
664         }
665         
666         m_tstools.openFile(file);
667         
668                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
669                    THEN DO A REAL FIX HERE! */
670         
671                 /* (this codepath needs to be improved anyway.) */
672         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
673         if (m_pvr_fd_dst < 0)
674         {
675                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
676                 return -ENODEV;
677         }
678         
679         m_pvr_fd_src = open(file, O_RDONLY);
680         if (m_pvr_fd_src < 0)
681         {
682                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
683                 close(m_pvr_fd_dst);
684                 return -ENOENT;
685         }
686         
687         m_state = state_ok;
688         m_stateChanged(this);
689         
690         m_pvr_thread = new eFilePushThread();
691         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
692
693         return 0;
694 }
695
696 RESULT eDVBChannel::getLength(pts_t &len)
697 {
698         return m_tstools.calcLen(len);
699 }
700
701 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos)
702 {
703         if (!decoding_demux)
704                 return -1;
705         
706         off_t begin = 0;
707                 /* getPTS for offset 0 is cached, so it doesn't harm. */
708         int r = m_tstools.getPTS(begin, pos);
709         if (r)
710         {
711                 eDebug("tstools getpts(0) failed!");
712                 return r;
713         }
714         
715         pts_t now;
716         
717         r = decoding_demux->getSTC(now);
718
719         if (r)
720         {
721                 eDebug("demux getSTC failed");
722                 return -1;
723         }
724         
725 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
726                 /* when we are less than 10 seconds before the start, return 0. */
727                 /* (we're just waiting for the timespam to start) */
728         if ((now < pos) && ((pos - now) < 90000 * 10))
729         {
730                 pos = 0;
731                 return 0;
732         }
733         
734         if (now < pos) /* wrap around */
735                 pos = now + ((pts_t)1)<<33 - pos;
736         else
737                 pos = now - pos;
738         
739         return 0;
740 }
741
742 RESULT eDVBChannel::seekTo(iDVBDemux *decoding_demux, int relative, pts_t &pts)
743 {
744         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
745         
746         if (bitrate == -1)
747                 return -1;
748         
749         if (relative)
750         {
751                 pts_t now;
752                 if (getCurrentPosition(decoding_demux, now))
753                 {
754                         eDebug("seekTo: getCurrentPosition failed!");
755                         return -1;
756                 }
757                 pts += now;
758         }
759         
760         if (pts < 0)
761                 pts = 0;
762         
763         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
764         
765         seekToPosition(decoding_demux, offset);
766         return 0;
767 }
768
769 RESULT eDVBChannel::seekToPosition(iDVBDemux *decoding_demux, const off_t &r)
770 {
771                         /* when seeking, we have to ensure that all buffers are flushed.
772                            there are basically 3 buffers:
773                            a.) the filepush's internal buffer
774                            b.) the PVR buffer (before demux)
775                            c.) the ratebuffer (after demux)
776                            
777                            it's important to clear them in the correct order, otherwise
778                            the ratebuffer (for example) would immediately refill from
779                            the not-yet-flushed PVR buffer.
780                         */
781         eDebug("eDVBChannel: seekToPosition .. %llx", r);
782         m_pvr_thread->pause();
783
784                 /* flush internal filepush buffer */
785         m_pvr_thread->flush();
786
787                 /* HACK: flush PVR buffer */
788         ::ioctl(m_pvr_fd_dst, 0);
789         
790                 /* flush ratebuffers (video, audio) */
791         if (decoding_demux)
792                 decoding_demux->flush();
793
794                 /* demux will also flush all decoder.. */
795         m_pvr_thread->seek(SEEK_SET, r);
796         m_pvr_thread->resume();
797         return 0;
798 }