remove generated file "config.h":
[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/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         bool ret=true;
444         if (m_cached_channel)
445         {
446                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
447                 if(channelid==cache_chan->getChannelID())
448                         return ret;
449         }
450
451                 /* first, check if a channel is already existing. */
452 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
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 == channelid)
457                 {
458 //                      eDebug("found shared channel..");
459                         return ret;
460                 }
461         }
462
463         int *decremented_cached_channel_fe_usecount=NULL,
464                 *decremented_fe_usecount=NULL;
465
466         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
467         {
468 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
469                 if (i->m_channel_id == ignore)
470                 {
471                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
472                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1)  // channel only used once..
473                         {
474                                 ePtr<iDVBFrontend> fe;
475                                 if (!i->m_channel->getFrontend(fe))
476                                 {
477                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
478                                         {
479                                                 if ( &(*fe) == &(*ii->m_frontend) )
480                                                 {
481                                                         --ii->m_inuse;
482                                                         decremented_fe_usecount = &ii->m_inuse;
483                                                         if (channel == &(*m_cached_channel))
484                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
485                                                         break;
486                                                 }
487                                         }
488                                 }
489                         }
490                         break;
491                 }
492         }
493
494         if (!decremented_cached_channel_fe_usecount)
495         {
496                 if (m_cached_channel)
497                 {
498                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
499                         if (channel->getUseCount() == 1)
500                         {
501                                 ePtr<iDVBFrontend> fe;
502                                 if (!channel->getFrontend(fe))
503                                 {
504                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
505                                         {
506                                                 if ( &(*fe) == &(*ii->m_frontend) )
507                                                 {
508                                                         --ii->m_inuse;
509                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
510                                                         break;
511                                                 }
512                                         }
513                                 }
514                         }
515                 }
516         }
517         else
518                 decremented_cached_channel_fe_usecount=NULL;
519
520         ePtr<iDVBFrontendParameters> feparm;
521
522         if (!m_list)
523         {
524                 eDebug("no channel list set!");
525                 ret = false;
526                 goto error;
527         }
528
529         if (m_list->getChannelFrontendData(channelid, feparm))
530         {
531                 eDebug("channel not found!");
532                 ret = false;
533                 goto error;
534         }
535
536         ret = canAllocateFrontend(feparm);
537
538 error:
539         if (decremented_fe_usecount)
540                 ++(*decremented_fe_usecount);
541         if (decremented_cached_channel_fe_usecount)
542                 ++(*decremented_cached_channel_fe_usecount);
543
544         return ret;
545 }
546
547 DEFINE_REF(eDVBChannel);
548
549 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
550 {
551         m_frontend = frontend;
552
553         m_pvr_thread = 0;
554         
555         if (m_frontend)
556                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
557 }
558
559 eDVBChannel::~eDVBChannel()
560 {
561         if (m_channel_id)
562                 m_mgr->removeChannel(this);
563         
564         if (m_pvr_thread)
565         {
566                 m_pvr_thread->stop();
567                 ::close(m_pvr_fd_src);
568                 ::close(m_pvr_fd_dst);
569                 delete m_pvr_thread;
570         }
571 }
572
573 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
574 {
575         int state, ourstate = 0;
576         
577                 /* if we are already in shutdown, don't change state. */
578         if (m_state == state_release)
579                 return;
580         
581         if (fe->getState(state))
582                 return;
583         
584         if (state == iDVBFrontend::stateLock)
585         {
586                 eDebug("OURSTATE: ok");
587                 ourstate = state_ok;
588         } else if (state == iDVBFrontend::stateTuning)
589         {
590                 eDebug("OURSTATE: tuning");
591                 ourstate = state_tuning;
592         } else if (state == iDVBFrontend::stateLostLock)
593         {
594                         /* on managed channels, we try to retune in order to re-acquire lock. */
595                 if (m_feparm)
596                 {
597                         eDebug("OURSTATE: lost lock, trying to retune");
598                         ourstate = state_tuning;
599                         m_frontend->get().tune(*m_feparm);
600                 } else
601                         /* on unmanaged channels, we don't do this. the client will do this. */
602                 {
603                         eDebug("OURSTATE: lost lock, unavailable now.");
604                         ourstate = state_unavailable;
605                 }
606         } else if (state == iDVBFrontend::stateFailed)
607         {
608                 eDebug("OURSTATE: failed");
609                 ourstate = state_failed;
610         } else
611                 eFatal("state unknown");
612         
613         if (ourstate != m_state)
614         {
615                 m_state = ourstate;
616                 m_stateChanged(this);
617         }
618 }
619
620 void eDVBChannel::pvrEvent(int event)
621 {
622         switch (event)
623         {
624         case eFilePushThread::evtEOF:
625                 eDebug("eDVBChannel: End of file!");
626                 m_event(this, evtEOF);
627                 break;
628         }
629 }
630
631 void eDVBChannel::AddUse()
632 {
633         ++m_use_count;
634 }
635
636 void eDVBChannel::ReleaseUse()
637 {
638         if (!--m_use_count)
639         {
640                 m_state = state_release;
641                 m_stateChanged(this);
642         }
643 }
644
645 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
646 {
647         if (m_channel_id)
648                 m_mgr->removeChannel(this);
649                 
650         if (!channelid)
651                 return 0;
652
653         if (!m_frontend)
654         {
655                 eDebug("no frontend to tune!");
656                 return -ENODEV;
657         }
658         
659         m_channel_id = channelid;
660         m_mgr->addChannel(channelid, this);
661         m_state = state_tuning;
662                         /* if tuning fails, shutdown the channel immediately. */
663         int res;
664         res = m_frontend->get().tune(*feparm);
665         m_feparm = feparm;
666         
667         if (res)
668         {
669                 m_state = state_release;
670                 m_stateChanged(this);
671                 return res;
672         }
673         
674         return 0;
675 }
676
677 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
678 {
679         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
680         return 0;
681 }
682
683 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
684 {
685         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
686         return 0;
687 }
688
689 RESULT eDVBChannel::getState(int &state)
690 {
691         state = m_state;
692         return 0;
693 }
694
695 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
696 {
697         return -1;
698 }
699
700 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
701 {
702         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
703         
704         if (!our_demux)
705         {
706                 demux = 0;
707                 
708                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
709                         return -1;
710         }
711         
712         demux = *our_demux;
713                 /* don't hold a reference to the decoding demux, we don't need it. */
714         if (cap & capDecode)
715                 our_demux = 0;
716         return 0;
717 }
718
719 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
720 {
721         frontend = &m_frontend->get();
722         if (frontend)
723                 return 0;
724         else
725                 return -ENODEV;
726 }
727
728 RESULT eDVBChannel::playFile(const char *file)
729 {
730         ASSERT(!m_frontend);
731         if (m_pvr_thread)
732         {
733                 m_pvr_thread->stop();
734                 delete m_pvr_thread;
735                 m_pvr_thread = 0;
736         }
737         
738         m_tstools.openFile(file);
739         
740                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
741                    THEN DO A REAL FIX HERE! */
742         
743                 /* (this codepath needs to be improved anyway.) */
744         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
745         if (m_pvr_fd_dst < 0)
746         {
747                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
748                 return -ENODEV;
749         }
750         
751         m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
752         if (m_pvr_fd_src < 0)
753         {
754                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
755                 close(m_pvr_fd_dst);
756                 return -ENOENT;
757         }
758         
759         m_state = state_ok;
760         m_stateChanged(this);
761         
762         m_pvr_thread = new eFilePushThread();
763         m_pvr_thread->enablePVRCommit(1);
764         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
765         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
766
767         return 0;
768 }
769
770 RESULT eDVBChannel::getLength(pts_t &len)
771 {
772         return m_tstools.calcLen(len);
773 }
774
775 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
776 {
777         if (!decoding_demux)
778                 return -1;
779         
780         off_t begin = 0;
781                 /* getPTS for offset 0 is cached, so it doesn't harm. */
782         int r = m_tstools.getPTS(begin, pos);
783         if (r)
784         {
785                 eDebug("tstools getpts(0) failed!");
786                 return r;
787         }
788         
789         pts_t now;
790         
791                         /* TODO: this is a gross hack. */
792         r = decoding_demux->getSTC(now, mode ? 128 : 0);
793
794         if (r)
795         {
796                 eDebug("demux getSTC failed");
797                 return -1;
798         }
799         
800 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
801                 /* when we are less than 10 seconds before the start, return 0. */
802                 /* (we're just waiting for the timespam to start) */
803         if ((now < pos) && ((pos - now) < 90000 * 10))
804         {
805                 pos = 0;
806                 return 0;
807         }
808         
809         if (now < pos) /* wrap around */
810                 pos = now + ((pts_t)1)<<33 - pos;
811         else
812                 pos = now - pos;
813         
814         return 0;
815 }
816
817 RESULT eDVBChannel::seekTo(iDVBDemux *decoding_demux, int relative, pts_t &pts)
818 {
819         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
820         
821         if (bitrate == -1)
822                 return -1;
823         
824         if (relative)
825         {
826                 pts_t now;
827                 if (getCurrentPosition(decoding_demux, now, 0))
828                 {
829                         eDebug("seekTo: getCurrentPosition failed!");
830                         return -1;
831                 }
832                 pts += now;
833         }
834         
835         if (pts < 0)
836                 pts = 0;
837         
838         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
839         
840         seekToPosition(decoding_demux, offset);
841         return 0;
842 }
843
844 RESULT eDVBChannel::seekToPosition(iDVBDemux *decoding_demux, const off_t &r)
845 {
846                         /* when seeking, we have to ensure that all buffers are flushed.
847                            there are basically 3 buffers:
848                            a.) the filepush's internal buffer
849                            b.) the PVR buffer (before demux)
850                            c.) the ratebuffer (after demux)
851                            
852                            it's important to clear them in the correct order, otherwise
853                            the ratebuffer (for example) would immediately refill from
854                            the not-yet-flushed PVR buffer.
855                         */
856         eDebug("eDVBChannel: seekToPosition .. %llx", r);
857         m_pvr_thread->pause();
858
859                 /* flush internal filepush buffer */
860         m_pvr_thread->flush();
861
862                 /* HACK: flush PVR buffer */
863         ::ioctl(m_pvr_fd_dst, 0);
864         
865                 /* flush ratebuffers (video, audio) */
866         if (decoding_demux)
867                 decoding_demux->flush();
868
869                 /* demux will also flush all decoder.. */
870         m_pvr_thread->seek(SEEK_SET, r);
871         m_pvr_thread->resume();
872         return 0;
873 }