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