dont use and show input power measurement (for rotor running detection),
[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/pmt.h>
6 #include <lib/dvb/sec.h>
7
8 #include <errno.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14
15 DEFINE_REF(eDVBRegisteredFrontend);
16 DEFINE_REF(eDVBRegisteredDemux);
17
18 DEFINE_REF(eDVBAllocatedFrontend);
19
20 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
21 {
22         m_fe->inc_use();
23 }
24
25 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
26 {
27         m_fe->dec_use();
28 }
29
30 DEFINE_REF(eDVBAllocatedDemux);
31
32 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
33 {
34         m_demux->m_inuse++;
35 }
36
37 eDVBAllocatedDemux::~eDVBAllocatedDemux()
38 {
39         --m_demux->m_inuse;
40 }
41
42 DEFINE_REF(eDVBResourceManager);
43
44 eDVBResourceManager *eDVBResourceManager::instance;
45
46 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
47 {
48         if (instance)
49         {
50                 ptr = instance;
51                 return 0;
52         }
53         return -1;
54 }
55
56 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
57 {
58         ePtr<eDVBResourceManager> ptr;
59         eDVBResourceManager::getInstance(ptr);
60         return ptr;
61 }
62
63 eDVBResourceManager::eDVBResourceManager()
64         :m_releaseCachedChannelTimer(eApp)
65 {
66         avail = 1;
67         busy = 0;
68         m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
69         if (!instance)
70                 instance = this;
71                 
72                 /* search available adapters... */
73
74                 // add linux devices
75         
76         int num_adapter = 0;
77         while (eDVBAdapterLinux::exist(num_adapter))
78         {
79                 addAdapter(new eDVBAdapterLinux(num_adapter));
80                 num_adapter++;
81         }
82         
83         eDebug("found %d adapter, %d frontends and %d demux", 
84                 m_adapter.size(), m_frontend.size(), m_demux.size());
85
86         eDVBCAService::registerChannelCallback(this);
87
88         CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
89 }
90
91 void eDVBResourceManager::feStateChanged()
92 {
93         int mask=0;
94         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
95                 if (i->m_inuse)
96                         mask |= ( 1 << i->m_frontend->getSlotID() );
97         /* emit */ frontendUseMaskChanged(mask);
98 }
99
100 DEFINE_REF(eDVBAdapterLinux);
101 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
102 {
103                 // scan frontends
104         int num_fe = 0;
105         
106         eDebug("scanning for frontends..");
107         while (1)
108         {
109                 struct stat s;
110                 char filename[128];
111 #if HAVE_DVB_API_VERSION < 3
112                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
113 #else
114                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
115 #endif
116                 if (stat(filename, &s))
117                         break;
118                 ePtr<eDVBFrontend> fe;
119
120                 int ok = 0;
121                 fe = new eDVBFrontend(m_nr, num_fe, ok);
122                 if (ok)
123                         m_frontend.push_back(fe);
124                 ++num_fe;
125         }
126         
127                 // scan demux
128         int num_demux = 0;
129         while (1)
130         {
131                 struct stat s;
132                 char filename[128];
133 #if HAVE_DVB_API_VERSION < 3
134                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
135 #else
136                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
137 #endif
138                 if (stat(filename, &s))
139                         break;
140                 ePtr<eDVBDemux> demux;
141                 
142                 demux = new eDVBDemux(m_nr, num_demux);
143                 m_demux.push_back(demux);
144                         
145                 ++num_demux;
146         }
147 }
148
149 int eDVBAdapterLinux::getNumDemux()
150 {
151         return m_demux.size();
152 }
153
154 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
155 {
156         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
157         while (nr && (i != m_demux.end()))
158         {
159                 --nr;
160                 ++i;
161         }
162         
163         if (i != m_demux.end())
164                 demux = *i;
165         else
166                 return -1;
167                 
168         return 0;
169 }
170
171 int eDVBAdapterLinux::getNumFrontends()
172 {
173         return m_frontend.size();
174 }
175
176 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
177 {
178         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
179         while (nr && (i != m_frontend.end()))
180         {
181                 --nr;
182                 ++i;
183         }
184         
185         if (i != m_frontend.end())
186                 fe = *i;
187         else
188                 return -1;
189                 
190         return 0;
191 }
192
193 int eDVBAdapterLinux::exist(int nr)
194 {
195         struct stat s;
196         char filename[128];
197 #if HAVE_DVB_API_VERSION < 3
198         sprintf(filename, "/dev/dvb/card%d", nr);
199 #else
200         sprintf(filename, "/dev/dvb/adapter%d", nr);
201 #endif
202         if (!stat(filename, &s))
203                 return 1;
204         return 0;
205 }
206
207 eDVBResourceManager::~eDVBResourceManager()
208 {
209         if (instance == this)
210                 instance = 0;
211 }
212
213 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
214 {
215         int num_fe = adapter->getNumFrontends();
216         int num_demux = adapter->getNumDemux();
217         
218         m_adapter.push_back(adapter);
219         
220         int i;
221         for (i=0; i<num_demux; ++i)
222         {
223                 ePtr<eDVBDemux> demux;
224                 if (!adapter->getDemux(demux, i))
225                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
226         }
227
228         ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
229         for (i=0; i<num_fe; ++i)
230         {
231                 ePtr<eDVBFrontend> frontend;
232                 if (!adapter->getFrontend(frontend, i))
233                 {
234                         int frontendType=0;
235                         frontend->getFrontendType(frontendType);
236                         eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
237                         CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
238                         m_frontend.push_back(new_fe);
239                         frontend->setSEC(m_sec);
240                         // we must link all dvb-t frontends ( for active antenna voltage )
241                         if (frontendType == iDVBFrontend::feTerrestrial)
242                         {
243                                 if (prev_dvbt_frontend)
244                                 {
245                                         prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
246                                         frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
247                                 }
248                                 prev_dvbt_frontend = new_fe;
249                         }
250                 }
251         }
252 }
253
254 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
255 {
256         if (!PyList_Check(list))
257         {
258                 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
259                 return NULL;
260         }
261         if ((unsigned int)PyList_Size(list) != m_frontend.size())
262         {
263                 char blasel[256];
264                 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
265                         m_frontend.size(), PyList_Size(list));
266                 PyErr_SetString(PyExc_StandardError, blasel);
267                 return NULL;
268         }
269         int pos=0;
270         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
271         {
272                 ePyObject obj = PyList_GET_ITEM(list, pos++);
273                 if (!i->m_frontend->setSlotInfo(obj))
274                         return NULL;
275         }
276         Py_RETURN_NONE;
277 }
278
279 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
280 {
281         ePtr<eDVBRegisteredFrontend> best;
282         int bestval = 0;
283         int foundone = 0;
284
285         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
286         {
287                 int c = i->m_frontend->isCompatibleWith(feparm);
288
289                 if (c)  /* if we have at least one frontend which is compatible with the source, flag this. */
290                         foundone = 1;
291
292                 if (!i->m_inuse)
293                 {
294                         if (c > bestval)
295                         {
296                                 bestval = c;
297                                 best = i;
298                         }
299                 }
300         }
301
302         if (best)
303         {
304                 fe = new eDVBAllocatedFrontend(best);
305                 return 0;
306         }
307
308         fe = 0;
309
310         if (foundone)
311                 return errAllSourcesBusy;
312         else
313                 return errNoSourceFound;
314 }
315
316 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
317 {
318         int err = errNoSourceFound;
319         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
320                 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
321                 {
322                         // check if another slot linked to this is in use
323                         eDVBRegisteredFrontend *satpos_depends_to_fe =
324                                 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
325                         if ( (long)satpos_depends_to_fe != -1 )
326                         {
327                                 if (satpos_depends_to_fe->m_inuse)
328                                 {
329                                         eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
330                                         err = errAllSourcesBusy;
331                                         goto alloc_fe_by_id_not_possible;
332                                 }
333                         }
334                         else // check linked tuners
335                         {
336                                 eDVBRegisteredFrontend *next =
337                                         (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
338                                 while ( (long)next != -1 )
339                                 {
340                                         if (next->m_inuse)
341                                         {
342                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
343                                                 err = errAllSourcesBusy;
344                                                 goto alloc_fe_by_id_not_possible;
345                                         }
346                                         next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
347                                 }
348                                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
349                                         i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
350                                 while ( (long)prev != -1 )
351                                 {
352                                         if (prev->m_inuse)
353                                         {
354                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
355                                                 err = errAllSourcesBusy;
356                                                 goto alloc_fe_by_id_not_possible;
357                                         }
358                                         prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
359                                 }
360                         }
361                         fe = new eDVBAllocatedFrontend(i);
362                         return 0;
363                 }
364 alloc_fe_by_id_not_possible:
365         fe = 0;
366         return err;
367 }
368
369 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
370 {
371                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
372                    never use the first one unless we need a decoding demux. */
373
374         eDebug("allocate demux");
375         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
376         
377         if (i == m_demux.end())
378                 return -1;
379                 
380         int n=0;
381                 /* FIXME: hardware demux policy */
382         if (!(cap & iDVBChannel::capDecode))
383         {
384                 if (m_demux.size() > 2)  /* assumed to be true, otherwise we have lost anyway */
385                 {
386                         ++i, ++n;
387                         ++i, ++n;
388                 }
389         }
390         
391         for (; i != m_demux.end(); ++i, ++n)
392         {
393                 int is_decode = n < 2;
394                 
395                 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
396                 
397                 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
398                 {
399                         if ((cap & iDVBChannel::capDecode) && !is_decode)
400                                 continue;
401                         
402                         demux = new eDVBAllocatedDemux(i);
403                         if (fe)
404                                 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
405                         else
406                                 demux->get().setSourcePVR(0);
407                         return 0;
408                 }
409         }
410         eDebug("demux not found");
411         return -1;
412 }
413
414 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
415 {
416         m_list = list;
417         return 0;
418 }
419
420 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
421 {
422         list = m_list;
423         if (list)
424                 return 0;
425         else
426                 return -ENOENT;
427 }
428
429 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
430 {
431                 /* first, check if a channel is already existing. */
432
433         if (m_cached_channel)
434         {
435                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
436                 if(channelid==cache_chan->getChannelID())
437                 {
438                         eDebug("use cached_channel");
439                         channel = m_cached_channel;
440                         return 0;
441                 }
442                 m_cached_channel_state_changed_conn.disconnect();
443                 m_cached_channel=0;
444                 m_releaseCachedChannelTimer.stop();
445         }
446
447 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
448         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
449         {
450 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
451                 if (i->m_channel_id == channelid)
452                 {
453 //                      eDebug("found shared channel..");
454                         channel = i->m_channel;
455                         return 0;
456                 }
457         }
458         
459         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
460
461         if (!m_list)
462         {
463                 eDebug("no channel list set!");
464                 return errNoChannelList;
465         }
466
467         ePtr<iDVBFrontendParameters> feparm;
468         if (m_list->getChannelFrontendData(channelid, feparm))
469         {
470                 eDebug("channel not found!");
471                 return errChannelNotInList;
472         }
473
474         /* allocate a frontend. */
475         
476         ePtr<eDVBAllocatedFrontend> fe;
477
478         int err = allocateFrontend(fe, feparm);
479         if (err)
480                 return err;
481
482         RESULT res;
483         ePtr<eDVBChannel> ch;
484         ch = new eDVBChannel(this, fe);
485
486         res = ch->setChannel(channelid, feparm);
487         if (res)
488         {
489                 channel = 0;
490                 return errChidNotFound;
491         }
492         m_cached_channel = channel = ch;
493         m_cached_channel_state_changed_conn =
494                 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
495
496         return 0;
497 }
498
499 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
500 {
501         int state=0;
502         chan->getState(state);
503         switch (state)
504         {
505                 case iDVBChannel::state_release:
506                 case iDVBChannel::state_ok:
507                 {
508                         eDebug("stop release channel timer");
509                         m_releaseCachedChannelTimer.stop();
510                         break;
511                 }
512                 case iDVBChannel::state_last_instance:
513                 {
514                         eDebug("start release channel timer");
515                         m_releaseCachedChannelTimer.start(3000, true);
516                         break;
517                 }
518                 default: // ignore all other events
519                         break;
520         }
521 }
522
523 void eDVBResourceManager::releaseCachedChannel()
524 {
525         eDebug("release cached channel (timer timeout)");
526         m_cached_channel=0;
527 }
528
529 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
530 {
531         ePtr<eDVBAllocatedFrontend> fe;
532
533         if (m_cached_channel)
534         {
535                 m_cached_channel_state_changed_conn.disconnect();
536                 m_cached_channel=0;
537                 m_releaseCachedChannelTimer.stop();
538         }
539
540         int err = allocateFrontendByIndex(fe, slot_index);
541         if (err)
542                 return err;
543
544         eDVBChannel *ch;
545         ch = new eDVBChannel(this, fe);
546
547         channel = ch;
548         return 0;
549 }
550
551
552 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
553 {
554         ePtr<eDVBAllocatedDemux> demux;
555
556         if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
557         {
558                 m_cached_channel_state_changed_conn.disconnect();
559                 m_cached_channel=0;
560                 m_releaseCachedChannelTimer.stop();
561         }
562
563         eDVBChannel *ch;
564         ch = new eDVBChannel(this, 0);
565
566         channel = ch;
567         return 0;
568 }
569
570 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
571 {
572         m_active_channels.push_back(active_channel(chid, ch));
573         /* emit */ m_channelAdded(ch);
574         return 0;
575 }
576
577 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
578 {
579         int cnt = 0;
580         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
581         {
582                 if (i->m_channel == ch)
583                 {
584                         i = m_active_channels.erase(i);
585                         ++cnt;
586                 } else
587                         ++i;
588         }
589         ASSERT(cnt == 1);
590         if (cnt == 1)
591                 return 0;
592         return -ENOENT;
593 }
594
595 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
596 {
597         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
598         return 0;
599 }
600
601 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
602 {
603         ePtr<eDVBRegisteredFrontend> best;
604         int bestval = 0;
605
606         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
607                 if (!i->m_inuse)
608                 {
609                         int c = i->m_frontend->isCompatibleWith(feparm);
610                         if (c > bestval)
611                                 bestval = c;
612                 }
613         return bestval;
614 }
615
616 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
617 {
618         if (channellist)
619         {
620                 ePtr<iDVBFrontendParameters> feparm;
621                 if (!channellist->getChannelFrontendData(chid, feparm))
622                 {
623                         int system;
624                         if (!feparm->getSystem(system))
625                         {
626                                 switch(system)
627                                 {
628                                         case iDVBFrontend::feSatellite:
629                                                 return 50000;
630                                         case iDVBFrontend::feCable:
631                                                 return 40000;
632                                         case iDVBFrontend::feTerrestrial:
633                                                 return 30000;
634                                         default:
635                                                 break;
636                                 }
637                         }
638                 }
639         }
640         return 0;
641 }
642
643 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
644 {
645         int ret=0;
646         if (m_cached_channel)
647         {
648                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
649                 if(channelid==cache_chan->getChannelID())
650                         return tuner_type_channel_default(m_list, channelid);
651         }
652
653                 /* first, check if a channel is already existing. */
654 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
655         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
656         {
657 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
658                 if (i->m_channel_id == channelid)
659                 {
660 //                      eDebug("found shared channel..");
661                         return tuner_type_channel_default(m_list, channelid);
662                 }
663         }
664
665         int *decremented_cached_channel_fe_usecount=NULL,
666                 *decremented_fe_usecount=NULL;
667
668         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
669         {
670 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
671                 if (i->m_channel_id == ignore)
672                 {
673                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
674                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
675                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
676                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
677                         // or 2 when the cached channel is not equal to the compared channel
678                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
679                         {
680                                 ePtr<iDVBFrontend> fe;
681                                 if (!i->m_channel->getFrontend(fe))
682                                 {
683                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
684                                         {
685                                                 if ( &(*fe) == &(*ii->m_frontend) )
686                                                 {
687                                                         --ii->m_inuse;
688                                                         decremented_fe_usecount = &ii->m_inuse;
689                                                         if (channel == &(*m_cached_channel))
690                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
691                                                         break;
692                                                 }
693                                         }
694                                 }
695                         }
696                         break;
697                 }
698         }
699
700         if (!decremented_cached_channel_fe_usecount)
701         {
702                 if (m_cached_channel)
703                 {
704                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
705                         if (channel->getUseCount() == 1)
706                         {
707                                 ePtr<iDVBFrontend> fe;
708                                 if (!channel->getFrontend(fe))
709                                 {
710                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
711                                         {
712                                                 if ( &(*fe) == &(*ii->m_frontend) )
713                                                 {
714                                                         --ii->m_inuse;
715                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
716                                                         break;
717                                                 }
718                                         }
719                                 }
720                         }
721                 }
722         }
723         else
724                 decremented_cached_channel_fe_usecount=NULL;
725
726         ePtr<iDVBFrontendParameters> feparm;
727
728         if (!m_list)
729         {
730                 eDebug("no channel list set!");
731                 goto error;
732         }
733
734         if (m_list->getChannelFrontendData(channelid, feparm))
735         {
736                 eDebug("channel not found!");
737                 goto error;
738         }
739
740         ret = canAllocateFrontend(feparm);
741
742 error:
743         if (decremented_fe_usecount)
744                 ++(*decremented_fe_usecount);
745         if (decremented_cached_channel_fe_usecount)
746                 ++(*decremented_cached_channel_fe_usecount);
747
748         return ret;
749 }
750
751 bool eDVBResourceManager::canMeasureFrontendInputPower()
752 {
753         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
754         {
755                 return i->m_frontend->readInputpower() >= 0;
756         }
757         return false;
758 }
759
760 class eDVBChannelFilePush: public eFilePushThread
761 {
762 public:
763         eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
764         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
765
766                         /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
767                         /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
768         void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
769 protected:
770         int m_iframe_search, m_iframe_state, m_pid;
771         int m_timebase_change;
772         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
773 };
774
775 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
776 {
777 #if 0
778         if (m_timebase_change)
779         {
780                 eDebug("timebase change: %d", m_timebase_change);
781                 int offset;
782                 for (offset = 0; offset < len; offset += 188)
783                 {
784                         unsigned char *pkt = (unsigned char*)_data + offset;
785                         if (pkt[1] & 0x40) /* pusi */
786                         {
787                                 if (pkt[3] & 0x20) // adaption field present?
788                                         pkt += pkt[4] + 4 + 1;  /* skip adaption field and header */
789                                 else
790                                         pkt += 4; /* skip header */
791                                 if (pkt[0] || pkt[1] || (pkt[2] != 1))
792                                 {
793                                         eWarning("broken startcode");
794                                         continue;
795                                 }
796
797                                 pts_t pts = 0;
798
799                                 if (pkt[7] & 0x80) // PTS present?
800                                 {
801                                         pts  = ((unsigned long long)(pkt[ 9]&0xE))  << 29;
802                                         pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
803                                         pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
804                                         pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
805                                         pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
806
807 #if 0
808                                         off_t off = 0;
809                                         RESULT r = m_tstools.fixupPTS(off, pts);
810                                         if (r)
811                                                 eWarning("fixup PTS while trickmode playback failed.\n");
812 #endif
813
814                                         int sec = pts / 90000;
815                                         int frm = pts % 90000;
816                                         int min = sec / 60;
817                                         sec %= 60;
818                                         int hr = min / 60;
819                                         min %= 60;
820                                         int d = hr / 24;
821                                         hr %= 24;
822
823 //                                      eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
824
825                                         pts += 0x80000000LL;
826                                         pts *= m_timebase_change;
827                                         pts >>= 16;
828
829                                         sec = pts / 90000;
830                                         frm = pts % 90000;
831                                         min = sec / 60;
832                                         sec %= 60;
833                                         hr = min / 60;
834                                         min %= 60;
835                                         d = hr / 24;
836                                         hr %= 24;
837
838 //                                      eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
839
840                                         pkt[9] &= ~0xE;
841                                         pkt[10] = 0;
842                                         pkt[11] &= ~1;
843                                         pkt[12] = 0;
844                                         pkt[13] &= ~1;
845
846                                         pkt[9]  |= (pts >> 29) & 0xE;
847                                         pkt[10] |= (pts >> 22) & 0xFF;
848                                         pkt[11] |= (pts >> 14) & 0xFE;
849                                         pkt[12] |= (pts >> 7) & 0xFF;
850                                         pkt[13] |= (pts << 1) & 0xFE;
851                                 }
852                         }
853                 }
854         }
855 #endif
856
857 #if 1 /* not yet */
858         if (!m_iframe_search)
859                 return len;
860
861         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
862
863 //      eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
864
865         unsigned char *d = data;
866         while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
867         {
868                 int offset = d - data;
869                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
870                 unsigned char *ts = data + ts_offset;
871                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
872
873                 if ((d[3] == 0) && (m_pid == pid))  /* picture start */
874                 {
875                         int picture_type = (d[5] >> 3) & 7;
876                         d += 4;
877
878 //                      eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
879
880                         if (m_iframe_state == 1)
881                         {
882                                         /* we are allowing data, and stop allowing data on the next frame. 
883                                            we now found a frame. so stop here. */
884                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
885                                 current_span_remaining = 0;
886                                 m_iframe_state = 0;
887                                 unsigned char *fts = ts + 188;
888                                 while (fts < (data + len))
889                                 {
890                                         fts[1] |= 0x1f;
891                                         fts[2] |= 0xff; /* drop packet */
892                                         fts += 188;
893                                 }
894
895                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
896                         } else
897                         {
898                                 if (picture_type != 1) /* we are only interested in I frames */
899                                         continue;
900
901                                 unsigned char *fts = data;
902                                 while (fts < ts)
903                                 {
904                                         fts[1] |= 0x1f;
905                                         fts[2] |= 0xff; /* drop packet */
906
907                                         fts += 188;
908                                 }
909                                                 /* force payload only */
910                                 ts[3] &= ~0x30;
911                                 ts[3] |=  0x10;
912
913 //                              memset(ts + 4, 0xFF, (offset % 188) - 4);
914
915                                 m_iframe_state = 1;
916                         }
917                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
918                 {
919                         if (m_pid != pid)
920                         {
921                                 eDebug("now locked to pid %04x", pid);
922                                 m_pid = pid;
923                         }
924 //                      m_pid = 0x6e;
925                         d += 4;
926                 } else
927                         d += 4; /* ignore */
928
929         }
930
931         if (m_iframe_state == 1)
932                 return len;
933         else
934                 return 0; /* we need find an iframe first */
935 #else
936         return len;
937 #endif
938 }
939
940 DEFINE_REF(eDVBChannel);
941
942 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
943 {
944         m_frontend = frontend;
945
946         m_pvr_thread = 0;
947         
948         m_skipmode_n = m_skipmode_m = 0;
949         
950         if (m_frontend)
951                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
952 }
953
954 eDVBChannel::~eDVBChannel()
955 {
956         if (m_channel_id)
957                 m_mgr->removeChannel(this);
958
959         stopFile();
960 }
961
962 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
963 {
964         int state, ourstate = 0;
965         
966                 /* if we are already in shutdown, don't change state. */
967         if (m_state == state_release)
968                 return;
969         
970         if (fe->getState(state))
971                 return;
972         
973         if (state == iDVBFrontend::stateLock)
974         {
975                 eDebug("OURSTATE: ok");
976                 ourstate = state_ok;
977         } else if (state == iDVBFrontend::stateTuning)
978         {
979                 eDebug("OURSTATE: tuning");
980                 ourstate = state_tuning;
981         } else if (state == iDVBFrontend::stateLostLock)
982         {
983                         /* on managed channels, we try to retune in order to re-acquire lock. */
984                 if (m_current_frontend_parameters)
985                 {
986                         eDebug("OURSTATE: lost lock, trying to retune");
987                         ourstate = state_tuning;
988                         m_frontend->get().tune(*m_current_frontend_parameters);
989                 } else
990                         /* on unmanaged channels, we don't do this. the client will do this. */
991                 {
992                         eDebug("OURSTATE: lost lock, unavailable now.");
993                         ourstate = state_unavailable;
994                 }
995         } else if (state == iDVBFrontend::stateFailed)
996         {
997                 eDebug("OURSTATE: failed");
998                 ourstate = state_failed;
999         } else
1000                 eFatal("state unknown");
1001         
1002         if (ourstate != m_state)
1003         {
1004                 m_state = ourstate;
1005                 m_stateChanged(this);
1006         }
1007 }
1008
1009 void eDVBChannel::pvrEvent(int event)
1010 {
1011         switch (event)
1012         {
1013         case eFilePushThread::evtEOF:
1014                 eDebug("eDVBChannel: End of file!");
1015                 m_event(this, evtEOF);
1016                 break;
1017         case eFilePushThread::evtUser: /* start */
1018                 eDebug("SOF");
1019                 m_event(this, evtSOF);
1020                 break;
1021         }
1022 }
1023
1024 void eDVBChannel::cueSheetEvent(int event)
1025 {
1026         switch (event)
1027         {
1028         case eCueSheet::evtSeek:
1029                 eDebug("seek.");
1030                 flushPVR(m_cue->m_decoding_demux);
1031                 break;
1032         case eCueSheet::evtSkipmode:
1033         {
1034                 {
1035                         m_cue->m_lock.WrLock();
1036                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1037                         m_cue->m_lock.Unlock();
1038                         eRdLocker l(m_cue->m_lock);
1039                         if (m_cue->m_skipmode_ratio)
1040                         {
1041                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1042                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1043                                                 /* i agree that this might look a bit like black magic. */
1044                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1045                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1046
1047                                 if (m_cue->m_skipmode_ratio < 0)
1048                                         m_skipmode_m -= m_skipmode_n;
1049
1050                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1051
1052                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1053                                 {
1054                                         eWarning("something is wrong with this calculation");
1055                                         m_skipmode_n = m_skipmode_m = 0;
1056                                 }
1057                         } else
1058                         {
1059                                 eDebug("skipmode ratio is 0, normal play");
1060                                 m_skipmode_n = m_skipmode_m = 0;
1061                         }
1062                 }
1063                 ASSERT(m_pvr_thread);
1064                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1065                 if (m_cue->m_skipmode_ratio != 0)
1066                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1067                 else
1068                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1069                 eDebug("flush pvr");
1070                 flushPVR(m_cue->m_decoding_demux);
1071                 eDebug("done");
1072                 break;
1073         }
1074         case eCueSheet::evtSpanChanged:
1075         {
1076                 m_source_span.clear();
1077                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1078                 {
1079                         off_t offset_in, offset_out;
1080                         pts_t pts_in = i->first, pts_out = i->second;
1081                         if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1082                         {
1083                                 eDebug("span translation failed.\n");
1084                                 continue;
1085                         }
1086                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1087                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1088                 }
1089                 break;
1090         }
1091         }
1092 }
1093
1094         /* align toward zero */
1095 static inline long long align(long long x, int align)
1096 {
1097         int sign = x < 0;
1098
1099         if (sign)
1100                 x = -x;
1101
1102         x -= x % align;
1103
1104         if (sign)
1105                 x = -x;
1106
1107         return x;
1108 }
1109
1110         /* remember, this gets called from another thread. */
1111 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1112 {
1113         const int blocksize = 188;
1114         unsigned int max = align(10*1024*1024, blocksize);
1115         current_offset = align(current_offset, blocksize);
1116         
1117         if (!m_cue)
1118         {
1119                 eDebug("no cue sheet. forcing normal play");
1120                 start = current_offset;
1121                 size = max;
1122                 return;
1123         }
1124
1125         m_cue->m_lock.RdLock();
1126         if (!m_cue->m_decoding_demux)
1127         {
1128                 start = current_offset;
1129                 size = max;
1130                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1131                 m_cue->m_lock.Unlock();
1132                 return;
1133         }
1134
1135         if (m_skipmode_n)
1136         {
1137                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1138                 max = align(m_skipmode_n, blocksize);
1139         }
1140
1141         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1142
1143         current_offset += align(m_skipmode_m, blocksize);
1144
1145         while (!m_cue->m_seek_requests.empty())
1146         {
1147                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1148                 m_cue->m_lock.Unlock();
1149                 m_cue->m_lock.WrLock();
1150                 m_cue->m_seek_requests.pop_front();
1151                 m_cue->m_lock.Unlock();
1152                 m_cue->m_lock.RdLock();
1153                 int relative = seek.first;
1154                 pts_t pts = seek.second;
1155
1156                 pts_t now = 0;
1157                 if (relative)
1158                 {
1159                         if (!m_cue->m_decoder)
1160                         {
1161                                 eDebug("no decoder - can't seek relative");
1162                                 continue;
1163                         }
1164                         if (m_cue->m_decoder->getPTS(0, now))
1165                         {
1166                                 eDebug("decoder getPTS failed, can't seek relative");
1167                                 continue;
1168                         }
1169                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1170                         {
1171                                 eDebug("seekTo: getCurrentPosition failed!");
1172                                 continue;
1173                         }
1174                 } else if (pts < 0) /* seek relative to end */
1175                 {
1176                         pts_t len;
1177                         if (!getLength(len))
1178                         {
1179                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1180                                 pts += len;
1181                         } else
1182                         {
1183                                 eWarning("getLength failed - can't seek relative to end!");
1184                                 continue;
1185                         }
1186                 }
1187                 
1188                 if (relative == 1) /* pts relative */
1189                 {
1190                         pts += now;
1191                         if (pts < 0)
1192                                 pts = 0;
1193                 }
1194
1195                 if (relative != 2)
1196                         if (pts < 0)
1197                                 pts = 0;
1198                 
1199                 if (relative == 2) /* AP relative */
1200                 {
1201                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1202                         pts_t nextap;
1203                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1204                         {
1205                                 pts = now - 90000; /* approx. 1s */
1206                                 eDebug("AP relative seeking failed!");
1207                         } else
1208                         {
1209                                 eDebug("next ap is %llx\n", pts);
1210                                 pts = nextap;
1211                         }
1212                 }
1213                 
1214                 off_t offset = 0;
1215                 if (m_tstools.getOffset(offset, pts))
1216                 {
1217                         eDebug("get offset for pts=%lld failed!", pts);
1218                         continue;
1219                 }
1220
1221                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1222                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1223         }
1224
1225         m_cue->m_lock.Unlock();
1226
1227         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1228         {
1229                 long long aligned_start = align(i->first, blocksize);
1230                 long long aligned_end = align(i->second, blocksize);
1231         
1232                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1233                 {
1234                         start = current_offset;
1235                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1236                         if ((aligned_end - current_offset) > max)
1237                                 size = max;
1238                         else
1239                                 size = aligned_end - current_offset;
1240                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1241                         return;
1242                 }
1243                 if (current_offset < aligned_start)
1244                 {
1245                                 /* ok, our current offset is in an 'out' zone. */
1246                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1247                         {
1248                                         /* in normal playback, just start at the next zone. */
1249                                 start = i->first;
1250
1251                                         /* size is not 64bit! */
1252                                 if ((i->second - i->first) > max)
1253                                         size = max;
1254                                 else
1255                                         size = aligned_end - aligned_start;
1256
1257                                 eDebug("skip");
1258                                 if (m_skipmode_m < 0)
1259                                 {
1260                                         eDebug("reached SOF");
1261                                                 /* reached SOF */
1262                                         m_skipmode_m = 0;
1263                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1264                                 }
1265                         } else
1266                         {
1267                                         /* when skipping reverse, however, choose the zone before. */
1268                                 --i;
1269                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1270                                 size_t len;
1271
1272                                 aligned_start = align(i->first, blocksize);
1273                                 aligned_end = align(i->second, blocksize);
1274
1275                                 if ((aligned_end - aligned_start) > max)
1276                                         len = max;
1277                                 else
1278                                         len = aligned_end - aligned_start;
1279
1280                                 start = aligned_end - len;
1281                                 eDebug("skipping to %llx, %d", start, len);
1282                         }
1283
1284                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1285                         return;
1286                 }
1287         }
1288
1289         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1290         {
1291                 eDebug("reached SOF");
1292                 m_skipmode_m = 0;
1293                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1294         }
1295
1296         start = current_offset;
1297         size = max;
1298
1299         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1300         return;
1301 }
1302
1303 void eDVBChannel::AddUse()
1304 {
1305         if (++m_use_count > 1 && m_state == state_last_instance)
1306         {
1307                 m_state = state_ok;
1308                 m_stateChanged(this);
1309         }
1310 }
1311
1312 void eDVBChannel::ReleaseUse()
1313 {
1314         if (!--m_use_count)
1315         {
1316                 m_state = state_release;
1317                 m_stateChanged(this);
1318         }
1319         else if (m_use_count == 1)
1320         {
1321                 m_state = state_last_instance;
1322                 m_stateChanged(this);
1323         }
1324 }
1325
1326 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1327 {
1328         if (m_channel_id)
1329                 m_mgr->removeChannel(this);
1330                 
1331         if (!channelid)
1332                 return 0;
1333
1334         if (!m_frontend)
1335         {
1336                 eDebug("no frontend to tune!");
1337                 return -ENODEV;
1338         }
1339         
1340         m_channel_id = channelid;
1341         m_mgr->addChannel(channelid, this);
1342         m_state = state_tuning;
1343                         /* if tuning fails, shutdown the channel immediately. */
1344         int res;
1345         res = m_frontend->get().tune(*feparm);
1346         m_current_frontend_parameters = feparm;
1347         
1348         if (res)
1349         {
1350                 m_state = state_release;
1351                 m_stateChanged(this);
1352                 return res;
1353         }
1354         
1355         return 0;
1356 }
1357
1358 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1359 {
1360         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1361         return 0;
1362 }
1363
1364 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1365 {
1366         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1367         return 0;
1368 }
1369
1370 RESULT eDVBChannel::getState(int &state)
1371 {
1372         state = m_state;
1373         return 0;
1374 }
1375
1376 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1377 {
1378         return -1;
1379 }
1380
1381 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1382 {
1383         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1384         
1385         if (!our_demux)
1386         {
1387                 demux = 0;
1388                 
1389                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1390                         return -1;
1391         }
1392         
1393         demux = *our_demux;
1394                 /* don't hold a reference to the decoding demux, we don't need it. */
1395                 
1396                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1397                    the refcount is lost. thus, decoding demuxes are never allocated. 
1398                    
1399                    this poses a big problem for PiP. */
1400         if (cap & capDecode)
1401                 our_demux = 0;
1402         return 0;
1403 }
1404
1405 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1406 {
1407         frontend = 0;
1408         if (!m_frontend)
1409                 return -ENODEV;
1410         frontend = &m_frontend->get();
1411         if (frontend)
1412                 return 0;
1413         return -ENODEV;
1414 }
1415
1416 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1417 {
1418         param = m_current_frontend_parameters;
1419         return 0;
1420 }
1421
1422 RESULT eDVBChannel::playFile(const char *file)
1423 {
1424         ASSERT(!m_frontend);
1425         if (m_pvr_thread)
1426         {
1427                 m_pvr_thread->stop();
1428                 delete m_pvr_thread;
1429                 m_pvr_thread = 0;
1430         }
1431         
1432         m_tstools.openFile(file);
1433         
1434                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1435                    THEN DO A REAL FIX HERE! */
1436         
1437                 /* (this codepath needs to be improved anyway.) */
1438 #if HAVE_DVB_API_VERSION < 3
1439         m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1440 #else
1441         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1442 #endif
1443         if (m_pvr_fd_dst < 0)
1444         {
1445                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1446                 return -ENODEV;
1447         }
1448
1449         m_pvr_thread = new eDVBChannelFilePush();
1450         m_pvr_thread->enablePVRCommit(1);
1451         m_pvr_thread->setStreamMode(1);
1452         m_pvr_thread->setScatterGather(this);
1453
1454         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1455         {
1456                 delete m_pvr_thread;
1457                 m_pvr_thread = 0;
1458                 eDebug("can't open PVR file %s (%m)", file);
1459                 return -ENOENT;
1460         }
1461         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1462
1463         m_state = state_ok;
1464         m_stateChanged(this);
1465
1466         return 0;
1467 }
1468
1469 void eDVBChannel::stopFile()
1470 {
1471         if (m_pvr_thread)
1472         {
1473                 m_pvr_thread->stop();
1474                 ::close(m_pvr_fd_dst);
1475                 delete m_pvr_thread;
1476                 m_pvr_thread = 0;
1477         }
1478 }
1479
1480 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1481 {
1482         m_conn_cueSheetEvent = 0;
1483         m_cue = cuesheet;
1484         if (m_cue)
1485                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1486 }
1487
1488 RESULT eDVBChannel::getLength(pts_t &len)
1489 {
1490         return m_tstools.calcLen(len);
1491 }
1492
1493 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1494 {
1495         if (!decoding_demux)
1496                 return -1;
1497         
1498         pts_t now;
1499         
1500         int r;
1501         
1502         if (mode == 0) /* demux */
1503         {
1504                 r = decoding_demux->getSTC(now, 0);
1505                 if (r)
1506                 {
1507                         eDebug("demux getSTC failed");
1508                         return -1;
1509                 }
1510         } else
1511                 now = pos; /* fixup supplied */
1512         
1513         off_t off = 0; /* TODO: fixme */
1514         r = m_tstools.fixupPTS(off, now);
1515         if (r)
1516         {
1517                 eDebug("fixup PTS failed");
1518                 return -1;
1519         }
1520         
1521         pos = now;
1522         
1523         return 0;
1524 }
1525
1526 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1527 {
1528                         /* when seeking, we have to ensure that all buffers are flushed.
1529                            there are basically 3 buffers:
1530                            a.) the filepush's internal buffer
1531                            b.) the PVR buffer (before demux)
1532                            c.) the ratebuffer (after demux)
1533                            
1534                            it's important to clear them in the correct order, otherwise
1535                            the ratebuffer (for example) would immediately refill from
1536                            the not-yet-flushed PVR buffer.
1537                         */
1538
1539         m_pvr_thread->pause();
1540                 /* flush internal filepush buffer */
1541         m_pvr_thread->flush();
1542                 /* HACK: flush PVR buffer */
1543         ::ioctl(m_pvr_fd_dst, 0);
1544         
1545                 /* flush ratebuffers (video, audio) */
1546         if (decoding_demux)
1547                 decoding_demux->flush();
1548
1549                 /* demux will also flush all decoder.. */
1550                 /* resume will re-query the SG */
1551         m_pvr_thread->resume();
1552 }
1553
1554 DEFINE_REF(eCueSheet);
1555
1556 eCueSheet::eCueSheet()
1557 {
1558         m_skipmode_ratio = 0;
1559 }
1560
1561 void eCueSheet::seekTo(int relative, const pts_t &pts)
1562 {
1563         m_lock.WrLock();
1564         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1565         m_lock.Unlock();
1566         m_event(evtSeek);
1567 }
1568         
1569 void eCueSheet::clear()
1570 {
1571         m_lock.WrLock();
1572         m_spans.clear();
1573         m_lock.Unlock();
1574 }
1575
1576 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1577 {
1578         assert(begin < end);
1579         m_lock.WrLock();
1580         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1581         m_lock.Unlock();
1582 }
1583
1584 void eCueSheet::commitSpans()
1585 {
1586         m_event(evtSpanChanged);
1587 }
1588
1589 void eCueSheet::setSkipmode(const pts_t &ratio)
1590 {
1591         m_lock.WrLock();
1592         m_skipmode_ratio = ratio;
1593         m_lock.Unlock();
1594         m_event(evtSkipmode);
1595 }
1596
1597 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1598 {
1599         m_decoding_demux = demux;
1600         m_decoder = decoder;
1601 }
1602
1603 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1604 {
1605         connection = new eConnection(this, m_event.connect(event));
1606         return 0;
1607 }