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