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