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