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