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