fix
[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         :m_releaseCachedChannelTimer(eApp)
47 {
48         avail = 1;
49         busy = 0;
50         m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
51         if (!instance)
52                 instance = this;
53                 
54                 /* search available adapters... */
55
56                 // add linux devices
57         
58         int num_adapter = 0;
59         while (eDVBAdapterLinux::exist(num_adapter))
60         {
61                 addAdapter(new eDVBAdapterLinux(num_adapter));
62                 num_adapter++;
63         }
64         
65         eDebug("found %d adapter, %d frontends and %d demux", 
66                 m_adapter.size(), m_frontend.size(), m_demux.size());
67
68         CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
69 }
70
71
72 DEFINE_REF(eDVBAdapterLinux);
73 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
74 {
75                 // scan frontends
76         int num_fe = 0;
77         
78         eDebug("scanning for frontends..");
79         while (1)
80         {
81                 struct stat s;
82                 char filename[128];
83 #if HAVE_DVB_API_VERSION < 3
84                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
85 #else
86                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
87 #endif
88                 if (stat(filename, &s))
89                         break;
90                 ePtr<eDVBFrontend> fe;
91
92                 int ok = 0;
93                 fe = new eDVBFrontend(m_nr, num_fe, ok);
94                 if (ok)
95                         m_frontend.push_back(fe);
96                 ++num_fe;
97         }
98         
99                 // scan demux
100         int num_demux = 0;
101         while (1)
102         {
103                 struct stat s;
104                 char filename[128];
105 #if HAVE_DVB_API_VERSION < 3
106                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
107 #else
108                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
109 #endif
110                 if (stat(filename, &s))
111                         break;
112                 ePtr<eDVBDemux> demux;
113                 
114                 demux = new eDVBDemux(m_nr, num_demux);
115                 m_demux.push_back(demux);
116                         
117                 ++num_demux;
118         }
119 }
120
121 int eDVBAdapterLinux::getNumDemux()
122 {
123         return m_demux.size();
124 }
125
126 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
127 {
128         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
129         while (nr && (i != m_demux.end()))
130         {
131                 --nr;
132                 ++i;
133         }
134         
135         if (i != m_demux.end())
136                 demux = *i;
137         else
138                 return -1;
139                 
140         return 0;
141 }
142
143 int eDVBAdapterLinux::getNumFrontends()
144 {
145         return m_frontend.size();
146 }
147
148 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
149 {
150         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
151         while (nr && (i != m_frontend.end()))
152         {
153                 --nr;
154                 ++i;
155         }
156         
157         if (i != m_frontend.end())
158                 fe = *i;
159         else
160                 return -1;
161                 
162         return 0;
163 }
164
165 int eDVBAdapterLinux::exist(int nr)
166 {
167         struct stat s;
168         char filename[128];
169 #if HAVE_DVB_API_VERSION < 3
170         sprintf(filename, "/dev/dvb/card%d", nr);
171 #else
172         sprintf(filename, "/dev/dvb/adapter%d", nr);
173 #endif
174         if (!stat(filename, &s))
175                 return 1;
176         return 0;
177 }
178
179 eDVBResourceManager::~eDVBResourceManager()
180 {
181         if (instance == this)
182                 instance = 0;
183 }
184
185 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
186 {
187         int num_fe = adapter->getNumFrontends();
188         int num_demux = adapter->getNumDemux();
189         
190         m_adapter.push_back(adapter);
191         
192         int i;
193         for (i=0; i<num_demux; ++i)
194         {
195                 ePtr<eDVBDemux> demux;
196                 if (!adapter->getDemux(demux, i))
197                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
198         }
199
200         for (i=0; i<num_fe; ++i)
201         {
202                 ePtr<eDVBFrontend> frontend;
203
204                 if (!adapter->getFrontend(frontend, i))
205                 {
206                         frontend->setSEC(m_sec);
207                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
208                 }
209         }
210 }
211
212 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
213 {
214         ePtr<eDVBRegisteredFrontend> best;
215         int bestval = 0;
216
217         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
218                 if (!i->m_inuse)
219                 {
220                         int c = i->m_frontend->isCompatibleWith(feparm);
221                         if (c > bestval)
222                         {
223                                 bestval = c;
224                                 best = i;
225                         }
226                 }
227
228         if (best)
229         {
230                 fe = new eDVBAllocatedFrontend(best);
231                 return 0;
232         }
233         
234         fe = 0;
235         
236         return -1;
237 }
238
239 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
240 {
241         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
242                 if ((!nr) && !i->m_inuse)
243                 {
244                         fe = new eDVBAllocatedFrontend(i);
245                         return 0;
246                 }
247         
248         fe = 0;
249         return -1;
250 }
251
252 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
253 {
254                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
255                    never use the first one unless we need a decoding demux. */
256
257         eDebug("allocate demux");
258         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
259         
260         if (i == m_demux.end())
261                 return -1;
262                 
263         int n=0;
264                 /* FIXME: hardware demux policy */
265         if (!(cap & iDVBChannel::capDecode))
266                 ++i, ++n;
267         
268         for (; i != m_demux.end(); ++i, ++n)
269                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
270                 {
271                         if ((cap & iDVBChannel::capDecode) && n)
272                                 continue;
273                         
274                         demux = new eDVBAllocatedDemux(i);
275                         if (fe)
276                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
277                         else
278                                 demux->get().setSourcePVR(0);
279                         return 0;
280                 }
281         eDebug("demux not found");
282         return -1;
283 }
284
285 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
286 {
287         m_list = list;
288         return 0;
289 }
290
291 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
292 {
293         list = m_list;
294         if (list)
295                 return 0;
296         else
297                 return -ENOENT;
298 }
299
300 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
301 {
302                 /* first, check if a channel is already existing. */
303
304         if (m_cached_channel)
305         {
306                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
307                 if(channelid==cache_chan->getChannelID())
308                 {
309                         eDebug("use cached_channel");
310                         channel = m_cached_channel;
311                         return 0;
312                 }
313                 m_cached_channel=0;
314         }
315
316 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
317         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
318         {
319 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
320                 if (i->m_channel_id == channelid)
321                 {
322 //                      eDebug("found shared channel..");
323                         channel = i->m_channel;
324                         return 0;
325                 }
326         }
327         
328         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
329
330         if (!m_list)
331         {
332                 eDebug("no channel list set!");
333                 return -ENOENT;
334         }
335
336         ePtr<iDVBFrontendParameters> feparm;
337         if (m_list->getChannelFrontendData(channelid, feparm))
338         {
339                 eDebug("channel not found!");
340                 return -ENOENT;
341         }
342
343         /* allocate a frontend. */
344         
345         ePtr<eDVBAllocatedFrontend> fe;
346         
347         if (allocateFrontend(fe, feparm))
348                 return errNoFrontend;
349
350         RESULT res;
351         ePtr<eDVBChannel> ch;
352         ch = new eDVBChannel(this, fe);
353
354         res = ch->setChannel(channelid, feparm);
355         if (res)
356         {
357                 channel = 0;
358                 return errChidNotFound;
359         }
360         m_cached_channel = channel = ch;
361         CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
362
363         return 0;
364 }
365
366 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
367 {
368         int state=0;
369         chan->getState(state);
370         switch (state)
371         {
372                 case iDVBChannel::state_release:
373                 case iDVBChannel::state_ok:
374                 {
375                         eDebug("stop release channel timer");
376                         m_releaseCachedChannelTimer.stop();
377                         break;
378                 }
379                 case iDVBChannel::state_last_instance:
380                 {
381                         eDebug("start release channel timer");
382                         m_releaseCachedChannelTimer.start(3000, true);
383                         break;
384                 }
385                 default: // ignore all other events
386                         break;
387         }
388 }
389
390 void eDVBResourceManager::releaseCachedChannel()
391 {
392         eDebug("release cached channel");
393         m_cached_channel=0;
394 }
395
396 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
397 {
398         ePtr<eDVBAllocatedFrontend> fe;
399
400         if (m_cached_channel)
401                 m_cached_channel=0;
402
403         if (allocateFrontendByIndex(fe, frontend_index))
404                 return errNoFrontend;
405         
406         eDVBChannel *ch;
407         ch = new eDVBChannel(this, fe);
408
409         channel = ch;
410         return 0;
411 }
412
413
414 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
415 {
416         ePtr<eDVBAllocatedDemux> demux;
417
418         if (m_cached_channel)
419                 m_cached_channel=0;
420
421         eDVBChannel *ch;
422         ch = new eDVBChannel(this, 0);
423         
424         channel = ch;
425         return 0;
426 }
427
428 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
429 {
430         m_active_channels.push_back(active_channel(chid, ch));
431         /* emit */ m_channelAdded(ch);
432         return 0;
433 }
434
435 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
436 {
437         int cnt = 0;
438         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
439         {
440                 if (i->m_channel == ch)
441                 {
442                         i = m_active_channels.erase(i);
443                         ++cnt;
444                 } else
445                         ++i;
446         }
447         ASSERT(cnt == 1);
448         if (cnt == 1)
449                 return 0;
450         return -ENOENT;
451 }
452
453 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
454 {
455         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
456         return 0;
457 }
458
459 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
460 {
461         ePtr<eDVBRegisteredFrontend> best;
462         int bestval = 0;
463
464         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
465                 if (!i->m_inuse)
466                 {
467                         int c = i->m_frontend->isCompatibleWith(feparm);
468                         if (c > bestval)
469                                 bestval = c;
470                 }
471
472         return bestval>0;
473 }
474
475 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
476 {
477         bool ret=true;
478         if (m_cached_channel)
479         {
480                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
481                 if(channelid==cache_chan->getChannelID())
482                         return ret;
483         }
484
485                 /* first, check if a channel is already existing. */
486 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
487         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
488         {
489 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
490                 if (i->m_channel_id == channelid)
491                 {
492 //                      eDebug("found shared channel..");
493                         return ret;
494                 }
495         }
496
497         int *decremented_cached_channel_fe_usecount=NULL,
498                 *decremented_fe_usecount=NULL;
499
500         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
501         {
502 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
503                 if (i->m_channel_id == ignore)
504                 {
505                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
506                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1)  // channel only used once..
507                         {
508                                 ePtr<iDVBFrontend> fe;
509                                 if (!i->m_channel->getFrontend(fe))
510                                 {
511                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
512                                         {
513                                                 if ( &(*fe) == &(*ii->m_frontend) )
514                                                 {
515                                                         --ii->m_inuse;
516                                                         decremented_fe_usecount = &ii->m_inuse;
517                                                         if (channel == &(*m_cached_channel))
518                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
519                                                         break;
520                                                 }
521                                         }
522                                 }
523                         }
524                         break;
525                 }
526         }
527
528         if (!decremented_cached_channel_fe_usecount)
529         {
530                 if (m_cached_channel)
531                 {
532                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
533                         if (channel->getUseCount() == 1)
534                         {
535                                 ePtr<iDVBFrontend> fe;
536                                 if (!channel->getFrontend(fe))
537                                 {
538                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
539                                         {
540                                                 if ( &(*fe) == &(*ii->m_frontend) )
541                                                 {
542                                                         --ii->m_inuse;
543                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
544                                                         break;
545                                                 }
546                                         }
547                                 }
548                         }
549                 }
550         }
551         else
552                 decremented_cached_channel_fe_usecount=NULL;
553
554         ePtr<iDVBFrontendParameters> feparm;
555
556         if (!m_list)
557         {
558                 eDebug("no channel list set!");
559                 ret = false;
560                 goto error;
561         }
562
563         if (m_list->getChannelFrontendData(channelid, feparm))
564         {
565                 eDebug("channel not found!");
566                 ret = false;
567                 goto error;
568         }
569
570         ret = canAllocateFrontend(feparm);
571
572 error:
573         if (decremented_fe_usecount)
574                 ++(*decremented_fe_usecount);
575         if (decremented_cached_channel_fe_usecount)
576                 ++(*decremented_cached_channel_fe_usecount);
577
578         return ret;
579 }
580
581 DEFINE_REF(eDVBChannel);
582
583 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
584 {
585         m_frontend = frontend;
586
587         m_pvr_thread = 0;
588         
589         m_skipmode_n = m_skipmode_m = 0;
590         
591         if (m_frontend)
592                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
593 }
594
595 eDVBChannel::~eDVBChannel()
596 {
597         if (m_channel_id)
598                 m_mgr->removeChannel(this);
599
600         stopFile();
601 }
602
603 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
604 {
605         int state, ourstate = 0;
606         
607                 /* if we are already in shutdown, don't change state. */
608         if (m_state == state_release)
609                 return;
610         
611         if (fe->getState(state))
612                 return;
613         
614         if (state == iDVBFrontend::stateLock)
615         {
616                 eDebug("OURSTATE: ok");
617                 ourstate = state_ok;
618         } else if (state == iDVBFrontend::stateTuning)
619         {
620                 eDebug("OURSTATE: tuning");
621                 ourstate = state_tuning;
622         } else if (state == iDVBFrontend::stateLostLock)
623         {
624                         /* on managed channels, we try to retune in order to re-acquire lock. */
625                 if (m_feparm)
626                 {
627                         eDebug("OURSTATE: lost lock, trying to retune");
628                         ourstate = state_tuning;
629                         m_frontend->get().tune(*m_feparm);
630                 } else
631                         /* on unmanaged channels, we don't do this. the client will do this. */
632                 {
633                         eDebug("OURSTATE: lost lock, unavailable now.");
634                         ourstate = state_unavailable;
635                 }
636         } else if (state == iDVBFrontend::stateFailed)
637         {
638                 eDebug("OURSTATE: failed");
639                 ourstate = state_failed;
640         } else
641                 eFatal("state unknown");
642         
643         if (ourstate != m_state)
644         {
645                 m_state = ourstate;
646                 m_stateChanged(this);
647         }
648 }
649
650 void eDVBChannel::pvrEvent(int event)
651 {
652         switch (event)
653         {
654         case eFilePushThread::evtEOF:
655                 eDebug("eDVBChannel: End of file!");
656                 m_event(this, evtEOF);
657                 break;
658         case eFilePushThread::evtUser: /* start */
659                 eDebug("SOF");
660                 m_event(this, evtSOF);
661                 break;
662         }
663 }
664
665 void eDVBChannel::cueSheetEvent(int event)
666 {
667         switch (event)
668         {
669         case eCueSheet::evtSeek:
670                 eDebug("seek.");
671                 flushPVR(m_cue->m_decoding_demux);
672                 break;
673         case eCueSheet::evtSkipmode:
674         {
675                 {
676                         eSingleLocker l(m_cue->m_lock);
677                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
678                         if (m_cue->m_skipmode_ratio)
679                         {
680                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
681                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
682                                                 /* i agree that this might look a bit like black magic. */
683                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
684                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio;
685         
686                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
687                                 
688                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
689                                 {
690                                         eFatal("damn, something is wrong with this calculation");
691                                         m_skipmode_n = m_skipmode_m = 0;
692                                 }
693                                 
694                         } else
695                         {
696                                 eDebug("skipmode ratio is 0, normal play");
697                                 m_skipmode_n = m_skipmode_m = 0;
698                         }
699                 }
700                 flushPVR(m_cue->m_decoding_demux);
701                 break;
702         }
703         case eCueSheet::evtSpanChanged:
704                 eDebug("source span translation not yet supported");
705         //      recheckCuesheetSpans();
706                 break;
707         }
708 }
709
710         /* remember, this gets called from another thread. */
711 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
712 {
713         unsigned int max = 10*1024*1024;
714         
715         if (!m_cue)
716         {
717                 eDebug("no cue sheet. forcing normal play");
718                 start = current_offset;
719                 size = max;
720                 return;
721         }
722
723         eSingleLocker l(m_cue->m_lock);
724         
725         if (!m_cue->m_decoding_demux)
726         {
727                 start = current_offset;
728                 size = max;
729                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
730                 return;
731         }
732         
733         if (m_skipmode_n)
734         {
735                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
736                 max = m_skipmode_n;
737         }
738         
739         eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
740         
741         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
742         {
743                 eDebug("reached SOF");
744                 m_skipmode_m = 0;
745                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
746         }
747         
748         current_offset += m_skipmode_m;
749         
750         while (!m_cue->m_seek_requests.empty())
751         {
752                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
753                 m_cue->m_seek_requests.pop_front();
754                 int relative = seek.first;
755                 pts_t pts = seek.second;
756
757                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
758         
759                 if (bitrate == -1)
760                         continue;
761         
762                 if (relative)
763                 {
764                         pts_t now;
765                                         /* we're using the decoder's timestamp here. this 
766                                            won't work for radio (ouch). */
767                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
768                         {
769                                 eDebug("seekTo: getCurrentPosition failed!");
770                                 continue;
771                         }
772                         pts += now;
773                 }
774         
775                 if (pts < 0)
776                         pts = 0;
777         
778                 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
779                 
780                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
781                 current_offset = offset;
782         }
783         
784         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
785         {
786                 if ((current_offset >= i->first) && (current_offset < i->second))
787                 {
788                         start = current_offset;
789                         size = i->second - current_offset;
790                         if (size > max)
791                                 size = max;
792                         eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
793                         return;
794                 }
795                 if (current_offset < i->first)
796                 {
797                         start = i->first;
798                         size = i->second - i->first;
799                         if (size > max)
800                                 size = max;
801                         eDebug("skip");
802                         return;
803                 }
804         }
805         
806         start = current_offset;
807         size = max;
808         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
809         
810         if (size < 4096)
811                 eFatal("blub");
812         return;
813 }
814
815 void eDVBChannel::AddUse()
816 {
817         if (++m_use_count > 1 && m_state == state_last_instance)
818         {
819                 m_state = state_ok;
820                 m_stateChanged(this);
821         }
822 }
823
824 void eDVBChannel::ReleaseUse()
825 {
826         if (!--m_use_count)
827         {
828                 m_state = state_release;
829                 m_stateChanged(this);
830         }
831         else if (m_use_count == 1)
832         {
833                 m_state = state_last_instance;
834                 m_stateChanged(this);
835         }
836 }
837
838 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
839 {
840         if (m_channel_id)
841                 m_mgr->removeChannel(this);
842                 
843         if (!channelid)
844                 return 0;
845
846         if (!m_frontend)
847         {
848                 eDebug("no frontend to tune!");
849                 return -ENODEV;
850         }
851         
852         m_channel_id = channelid;
853         m_mgr->addChannel(channelid, this);
854         m_state = state_tuning;
855                         /* if tuning fails, shutdown the channel immediately. */
856         int res;
857         res = m_frontend->get().tune(*feparm);
858         m_feparm = feparm;
859         
860         if (res)
861         {
862                 m_state = state_release;
863                 m_stateChanged(this);
864                 return res;
865         }
866         
867         return 0;
868 }
869
870 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
871 {
872         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
873         return 0;
874 }
875
876 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
877 {
878         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
879         return 0;
880 }
881
882 RESULT eDVBChannel::getState(int &state)
883 {
884         state = m_state;
885         return 0;
886 }
887
888 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
889 {
890         return -1;
891 }
892
893 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
894 {
895         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
896         
897         if (!our_demux)
898         {
899                 demux = 0;
900                 
901                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
902                         return -1;
903         }
904         
905         demux = *our_demux;
906                 /* don't hold a reference to the decoding demux, we don't need it. */
907         if (cap & capDecode)
908                 our_demux = 0;
909         return 0;
910 }
911
912 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
913 {
914         frontend = &m_frontend->get();
915         if (frontend)
916                 return 0;
917         else
918                 return -ENODEV;
919 }
920
921 RESULT eDVBChannel::playFile(const char *file)
922 {
923         ASSERT(!m_frontend);
924         if (m_pvr_thread)
925         {
926                 m_pvr_thread->stop();
927                 delete m_pvr_thread;
928                 m_pvr_thread = 0;
929         }
930         
931         m_tstools.openFile(file);
932         
933                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
934                    THEN DO A REAL FIX HERE! */
935         
936                 /* (this codepath needs to be improved anyway.) */
937         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
938         if (m_pvr_fd_dst < 0)
939         {
940                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
941                 return -ENODEV;
942         }
943         
944         m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
945         if (m_pvr_fd_src < 0)
946         {
947                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
948                 close(m_pvr_fd_dst);
949                 return -ENOENT;
950         }
951         
952         m_state = state_ok;
953         m_stateChanged(this);
954         
955         m_pvr_thread = new eFilePushThread();
956         m_pvr_thread->enablePVRCommit(1);
957         m_pvr_thread->setScatterGather(this);
958
959         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
960         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
961
962         return 0;
963 }
964
965 void eDVBChannel::stopFile()
966 {
967         if (m_pvr_thread)
968         {
969                 m_pvr_thread->stop();
970                 ::close(m_pvr_fd_src);
971                 ::close(m_pvr_fd_dst);
972                 delete m_pvr_thread;
973                 m_pvr_thread = 0;
974         }
975 }
976
977 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
978 {
979         m_conn_cueSheetEvent = 0;
980         m_cue = cuesheet;
981         if (m_cue)
982                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
983 }
984
985 RESULT eDVBChannel::getLength(pts_t &len)
986 {
987         return m_tstools.calcLen(len);
988 }
989
990 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
991 {
992         if (!decoding_demux)
993                 return -1;
994         
995         off_t begin = 0;
996                 /* getPTS for offset 0 is cached, so it doesn't harm. */
997         int r = m_tstools.getPTS(begin, pos);
998         if (r)
999         {
1000                 eDebug("tstools getpts(0) failed!");
1001                 return r;
1002         }
1003         
1004         pts_t now;
1005         
1006                         /* TODO: this is a gross hack. */
1007         r = decoding_demux->getSTC(now, mode ? 128 : 0);
1008
1009         if (r)
1010         {
1011                 eDebug("demux getSTC failed");
1012                 return -1;
1013         }
1014         
1015 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
1016                 /* when we are less than 10 seconds before the start, return 0. */
1017                 /* (we're just waiting for the timespam to start) */
1018         if ((now < pos) && ((pos - now) < 90000 * 10))
1019         {
1020                 pos = 0;
1021                 return 0;
1022         }
1023         
1024         if (now < pos) /* wrap around */
1025                 pos = now + ((pts_t)1)<<33 - pos;
1026         else
1027                 pos = now - pos;
1028         
1029         return 0;
1030 }
1031
1032 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1033 {
1034                         /* when seeking, we have to ensure that all buffers are flushed.
1035                            there are basically 3 buffers:
1036                            a.) the filepush's internal buffer
1037                            b.) the PVR buffer (before demux)
1038                            c.) the ratebuffer (after demux)
1039                            
1040                            it's important to clear them in the correct order, otherwise
1041                            the ratebuffer (for example) would immediately refill from
1042                            the not-yet-flushed PVR buffer.
1043                         */
1044
1045         m_pvr_thread->pause();
1046                 /* flush internal filepush buffer */
1047         m_pvr_thread->flush();
1048                 /* HACK: flush PVR buffer */
1049         ::ioctl(m_pvr_fd_dst, 0);
1050         
1051                 /* flush ratebuffers (video, audio) */
1052         if (decoding_demux)
1053                 decoding_demux->flush();
1054
1055                 /* demux will also flush all decoder.. */
1056                 /* resume will re-query the SG */
1057         m_pvr_thread->resume();
1058 }
1059
1060 DEFINE_REF(eCueSheet);
1061
1062 eCueSheet::eCueSheet()
1063 {
1064         m_skipmode_ratio = 0;
1065 }
1066
1067 void eCueSheet::seekTo(int relative, const pts_t &pts)
1068 {
1069         {
1070                 eSingleLock l(m_lock);
1071                 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1072         }
1073         m_event(evtSeek);
1074 }
1075         
1076 void eCueSheet::clear()
1077 {
1078         eSingleLock l(m_lock);
1079         m_spans.clear();
1080 }
1081
1082 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1083 {
1084         {
1085                 eSingleLock l(m_lock);
1086                 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1087         }
1088         m_event(evtSpanChanged);
1089 }
1090
1091 void eCueSheet::setSkipmode(const pts_t &ratio)
1092 {
1093         {
1094                 eSingleLock l(m_lock);
1095                 m_skipmode_ratio = ratio;
1096         }
1097         m_event(evtSkipmode);
1098 }
1099
1100 void eCueSheet::setDecodingDemux(iDVBDemux *demux)
1101 {
1102         m_decoding_demux = demux;
1103 }
1104
1105 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1106 {
1107         connection = new eConnection(this, m_event.connect(event));
1108         return 0;
1109 }