add HACK for wrong transmitted Cablecom EPG!
[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, (int)new_fe);
246                                         frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*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 ( (int)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 ( (int)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 ( (int)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 class eDVBChannelFilePush: public eFilePushThread
752 {
753 public:
754         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
755 protected:
756         int m_iframe_search, m_iframe_state, m_pid;
757         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
758 };
759
760 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
761 {
762 #if 0 /* not yet */
763         if (!m_iframe_search)
764                 return len;
765
766         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
767
768         eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
769
770         unsigned char *d = data;
771         while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
772         {
773                 int offset = d - data;
774                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
775                 unsigned char *ts = data + ts_offset;
776                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
777
778                 if ((d[3] == 0) && (m_pid == pid))  /* picture start */
779                 {
780                         int picture_type = (d[5] >> 3) & 7;
781                         d += 4;
782                         
783                         eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
784
785                         if (m_iframe_state == 1)
786                         {
787                                         /* we are allowing data, and stop allowing data on the next frame. 
788                                            we now found a frame. so stop here. */
789                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
790                                 current_span_remaining = 0;
791                                 m_iframe_state = 0;
792                                 unsigned char *fts = ts + 188;
793                                 while (fts < (data + len))
794                                 {
795                                         fts[1] |= 0x1f;
796                                         fts[2] |= 0xff; /* drop packet */
797                                         fts += 188;
798                                 }
799
800                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
801                         } else
802                         {
803                                 if (picture_type != 1) /* we are only interested in I frames */
804                                         continue;
805                         
806                                 unsigned char *fts = data;
807                                 while (fts < ts)
808                                 {
809                                         fts[1] |= 0x1f;
810                                         fts[2] |= 0xff; /* drop packet */
811                                 
812                                         fts += 188;
813                                 }
814                                                 /* force payload only */
815                                 ts[3] &= ~0x30;
816                                 ts[3] |=  0x10;
817                                 
818 //                              memset(ts + 4, 0xFF, (offset % 188) - 4);
819
820                                 m_iframe_state = 1;
821                         }
822                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
823                 {
824                         if (m_pid != pid)
825                         {
826                                 eDebug("now locked to pid %04x", pid);
827                                 m_pid = pid;
828                         }
829 //                      m_pid = 0x6e;
830                         d += 4;
831                 } else
832                         d += 4; /* ignore */
833
834         }
835
836         if (m_iframe_state == 1)
837                 return len;
838         else
839                 return 0; /* we need find an iframe first */
840 #else
841         return len;
842 #endif
843 }
844
845 DEFINE_REF(eDVBChannel);
846
847 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
848 {
849         m_frontend = frontend;
850
851         m_pvr_thread = 0;
852         
853         m_skipmode_n = m_skipmode_m = 0;
854         
855         if (m_frontend)
856                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
857 }
858
859 eDVBChannel::~eDVBChannel()
860 {
861         if (m_channel_id)
862                 m_mgr->removeChannel(this);
863
864         stopFile();
865 }
866
867 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
868 {
869         int state, ourstate = 0;
870         
871                 /* if we are already in shutdown, don't change state. */
872         if (m_state == state_release)
873                 return;
874         
875         if (fe->getState(state))
876                 return;
877         
878         if (state == iDVBFrontend::stateLock)
879         {
880                 eDebug("OURSTATE: ok");
881                 ourstate = state_ok;
882         } else if (state == iDVBFrontend::stateTuning)
883         {
884                 eDebug("OURSTATE: tuning");
885                 ourstate = state_tuning;
886         } else if (state == iDVBFrontend::stateLostLock)
887         {
888                         /* on managed channels, we try to retune in order to re-acquire lock. */
889                 if (m_current_frontend_parameters)
890                 {
891                         eDebug("OURSTATE: lost lock, trying to retune");
892                         ourstate = state_tuning;
893                         m_frontend->get().tune(*m_current_frontend_parameters);
894                 } else
895                         /* on unmanaged channels, we don't do this. the client will do this. */
896                 {
897                         eDebug("OURSTATE: lost lock, unavailable now.");
898                         ourstate = state_unavailable;
899                 }
900         } else if (state == iDVBFrontend::stateFailed)
901         {
902                 eDebug("OURSTATE: failed");
903                 ourstate = state_failed;
904         } else
905                 eFatal("state unknown");
906         
907         if (ourstate != m_state)
908         {
909                 m_state = ourstate;
910                 m_stateChanged(this);
911         }
912 }
913
914 void eDVBChannel::pvrEvent(int event)
915 {
916         switch (event)
917         {
918         case eFilePushThread::evtEOF:
919                 eDebug("eDVBChannel: End of file!");
920                 m_event(this, evtEOF);
921                 break;
922         case eFilePushThread::evtUser: /* start */
923                 eDebug("SOF");
924                 m_event(this, evtSOF);
925                 break;
926         }
927 }
928
929 void eDVBChannel::cueSheetEvent(int event)
930 {
931         switch (event)
932         {
933         case eCueSheet::evtSeek:
934                 eDebug("seek.");
935                 flushPVR(m_cue->m_decoding_demux);
936                 break;
937         case eCueSheet::evtSkipmode:
938         {
939                 {
940                         m_cue->m_lock.WrLock();
941                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
942                         m_cue->m_lock.Unlock();
943                         eRdLocker l(m_cue->m_lock);
944                         if (m_cue->m_skipmode_ratio)
945                         {
946                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
947                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
948                                                 /* i agree that this might look a bit like black magic. */
949                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
950                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
951                                 
952                                 if (m_cue->m_skipmode_ratio < 0)
953                                         m_skipmode_m -= m_skipmode_n;
954         
955                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
956                                 
957                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
958                                 {
959                                         eWarning("something is wrong with this calculation");
960                                         m_skipmode_n = m_skipmode_m = 0;
961                                 }
962                                 
963                         } else
964                         {
965                                 eDebug("skipmode ratio is 0, normal play");
966                                 m_skipmode_n = m_skipmode_m = 0;
967                         }
968                 }
969                 ASSERT(m_pvr_thread);
970                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
971                 eDebug("flush pvr");
972                 flushPVR(m_cue->m_decoding_demux);
973                 eDebug("done");
974                 break;
975         }
976         case eCueSheet::evtSpanChanged:
977         {
978                 m_source_span.clear();
979                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
980                 {
981                         off_t offset_in, offset_out;
982                         pts_t pts_in = i->first, pts_out = i->second;
983                         if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
984                         {
985                                 eDebug("span translation failed.\n");
986                                 continue;
987                         }
988                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
989                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
990                 }
991                 break;
992         }
993         }
994 }
995
996         /* align toward zero */
997 static inline long long align(long long x, int align)
998 {
999         int sign = x < 0;
1000
1001         if (sign)
1002                 x = -x;
1003
1004         x -= x % align;
1005
1006         if (sign)
1007                 x = -x;
1008
1009         return x;
1010 }
1011
1012         /* remember, this gets called from another thread. */
1013 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1014 {
1015         const int blocksize = 188;
1016         unsigned int max = align(10*1024*1024, blocksize);
1017         current_offset = align(current_offset, blocksize);
1018         
1019         if (!m_cue)
1020         {
1021                 eDebug("no cue sheet. forcing normal play");
1022                 start = current_offset;
1023                 size = max;
1024                 return;
1025         }
1026
1027         m_cue->m_lock.RdLock();
1028         if (!m_cue->m_decoding_demux)
1029         {
1030                 start = current_offset;
1031                 size = max;
1032                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1033                 m_cue->m_lock.Unlock();
1034                 return;
1035         }
1036
1037         if (m_skipmode_n)
1038         {
1039                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1040                 max = align(m_skipmode_n, blocksize);
1041         }
1042
1043         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1044
1045         current_offset += align(m_skipmode_m, blocksize);
1046
1047         while (!m_cue->m_seek_requests.empty())
1048         {
1049                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1050                 m_cue->m_lock.Unlock();
1051                 m_cue->m_lock.WrLock();
1052                 m_cue->m_seek_requests.pop_front();
1053                 m_cue->m_lock.Unlock();
1054                 m_cue->m_lock.RdLock();
1055                 int relative = seek.first;
1056                 pts_t pts = seek.second;
1057
1058                 pts_t now = 0;
1059                 if (relative)
1060                 {
1061                         if (!m_cue->m_decoder)
1062                         {
1063                                 eDebug("no decoder - can't seek relative");
1064                                 continue;
1065                         }
1066                         if (m_cue->m_decoder->getPTS(0, now))
1067                         {
1068                                 eDebug("decoder getPTS failed, can't seek relative");
1069                                 continue;
1070                         }
1071                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1072                         {
1073                                 eDebug("seekTo: getCurrentPosition failed!");
1074                                 continue;
1075                         }
1076                 } else if (pts < 0) /* seek relative to end */
1077                 {
1078                         pts_t len;
1079                         if (!getLength(len))
1080                         {
1081                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1082                                 pts += len;
1083                         } else
1084                         {
1085                                 eWarning("getLength failed - can't seek relative to end!");
1086                                 continue;
1087                         }
1088                 }
1089                 
1090                 if (relative == 1) /* pts relative */
1091                 {
1092                         pts += now;
1093                         if (pts < 0)
1094                                 pts = 0;
1095                 }
1096
1097                 if (relative != 2)
1098                         if (pts < 0)
1099                                 pts = 0;
1100                 
1101                 if (relative == 2) /* AP relative */
1102                 {
1103                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1104                         pts_t nextap;
1105                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1106                         {
1107                                 pts = now - 90000; /* approx. 1s */
1108                                 eDebug("AP relative seeking failed!");
1109                         } else
1110                         {
1111                                 eDebug("next ap is %llx\n", pts);
1112                                 pts = nextap;
1113                         }
1114                 }
1115                 
1116                 off_t offset = 0;
1117                 if (m_tstools.getOffset(offset, pts))
1118                 {
1119                         eDebug("get offset for pts=%lld failed!", pts);
1120                         continue;
1121                 }
1122
1123                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1124                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1125         }
1126
1127         m_cue->m_lock.Unlock();
1128
1129         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1130         {
1131                 long long aligned_start = align(i->first, blocksize);
1132                 long long aligned_end = align(i->second, blocksize);
1133         
1134                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1135                 {
1136                         start = current_offset;
1137                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1138                         if ((aligned_end - current_offset) > max)
1139                                 size = max;
1140                         else
1141                                 size = aligned_end - current_offset;
1142                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1143                         return;
1144                 }
1145                 if (current_offset < aligned_start)
1146                 {
1147                                 /* ok, our current offset is in an 'out' zone. */
1148                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1149                         {
1150                                         /* in normal playback, just start at the next zone. */
1151                                 start = i->first;
1152
1153                                         /* size is not 64bit! */
1154                                 if ((i->second - i->first) > max)
1155                                         size = max;
1156                                 else
1157                                         size = aligned_end - aligned_start;
1158
1159                                 eDebug("skip");
1160                                 if (m_skipmode_m < 0)
1161                                 {
1162                                         eDebug("reached SOF");
1163                                                 /* reached SOF */
1164                                         m_skipmode_m = 0;
1165                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1166                                 }
1167                         } else
1168                         {
1169                                         /* when skipping reverse, however, choose the zone before. */
1170                                 --i;
1171                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1172                                 size_t len;
1173
1174                                 aligned_start = align(i->first, blocksize);
1175                                 aligned_end = align(i->second, blocksize);
1176
1177                                 if ((aligned_end - aligned_start) > max)
1178                                         len = max;
1179                                 else
1180                                         len = aligned_end - aligned_start;
1181
1182                                 start = aligned_end - len;
1183                                 eDebug("skipping to %llx, %d", start, len);
1184                         }
1185
1186                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1187                         return;
1188                 }
1189         }
1190
1191         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1192         {
1193                 eDebug("reached SOF");
1194                 m_skipmode_m = 0;
1195                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1196         }
1197
1198         start = current_offset;
1199         size = max;
1200
1201         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1202         return;
1203 }
1204
1205 void eDVBChannel::AddUse()
1206 {
1207         if (++m_use_count > 1 && m_state == state_last_instance)
1208         {
1209                 m_state = state_ok;
1210                 m_stateChanged(this);
1211         }
1212 }
1213
1214 void eDVBChannel::ReleaseUse()
1215 {
1216         if (!--m_use_count)
1217         {
1218                 m_state = state_release;
1219                 m_stateChanged(this);
1220         }
1221         else if (m_use_count == 1)
1222         {
1223                 m_state = state_last_instance;
1224                 m_stateChanged(this);
1225         }
1226 }
1227
1228 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1229 {
1230         if (m_channel_id)
1231                 m_mgr->removeChannel(this);
1232                 
1233         if (!channelid)
1234                 return 0;
1235
1236         if (!m_frontend)
1237         {
1238                 eDebug("no frontend to tune!");
1239                 return -ENODEV;
1240         }
1241         
1242         m_channel_id = channelid;
1243         m_mgr->addChannel(channelid, this);
1244         m_state = state_tuning;
1245                         /* if tuning fails, shutdown the channel immediately. */
1246         int res;
1247         res = m_frontend->get().tune(*feparm);
1248         m_current_frontend_parameters = feparm;
1249         
1250         if (res)
1251         {
1252                 m_state = state_release;
1253                 m_stateChanged(this);
1254                 return res;
1255         }
1256         
1257         return 0;
1258 }
1259
1260 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1261 {
1262         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1263         return 0;
1264 }
1265
1266 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1267 {
1268         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1269         return 0;
1270 }
1271
1272 RESULT eDVBChannel::getState(int &state)
1273 {
1274         state = m_state;
1275         return 0;
1276 }
1277
1278 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1279 {
1280         return -1;
1281 }
1282
1283 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1284 {
1285         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1286         
1287         if (!our_demux)
1288         {
1289                 demux = 0;
1290                 
1291                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1292                         return -1;
1293         }
1294         
1295         demux = *our_demux;
1296                 /* don't hold a reference to the decoding demux, we don't need it. */
1297                 
1298                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1299                    the refcount is lost. thus, decoding demuxes are never allocated. 
1300                    
1301                    this poses a big problem for PiP. */
1302         if (cap & capDecode)
1303                 our_demux = 0;
1304         return 0;
1305 }
1306
1307 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1308 {
1309         frontend = 0;
1310         if (!m_frontend)
1311                 return -ENODEV;
1312         frontend = &m_frontend->get();
1313         if (frontend)
1314                 return 0;
1315         return -ENODEV;
1316 }
1317
1318 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1319 {
1320         param = m_current_frontend_parameters;
1321         return 0;
1322 }
1323
1324 RESULT eDVBChannel::playFile(const char *file)
1325 {
1326         ASSERT(!m_frontend);
1327         if (m_pvr_thread)
1328         {
1329                 m_pvr_thread->stop();
1330                 delete m_pvr_thread;
1331                 m_pvr_thread = 0;
1332         }
1333         
1334         m_tstools.openFile(file);
1335         
1336                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1337                    THEN DO A REAL FIX HERE! */
1338         
1339                 /* (this codepath needs to be improved anyway.) */
1340 #if HAVE_DVB_API_VERSION < 3
1341         m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1342 #else
1343         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1344 #endif
1345         if (m_pvr_fd_dst < 0)
1346         {
1347                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1348                 return -ENODEV;
1349         }
1350
1351         m_pvr_thread = new eDVBChannelFilePush();
1352         m_pvr_thread->enablePVRCommit(1);
1353         m_pvr_thread->setStreamMode(1);
1354         m_pvr_thread->setScatterGather(this);
1355
1356         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1357         {
1358                 delete m_pvr_thread;
1359                 m_pvr_thread = 0;
1360                 eDebug("can't open PVR file %s (%m)", file);
1361                 return -ENOENT;
1362         }
1363         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1364
1365         m_state = state_ok;
1366         m_stateChanged(this);
1367
1368         return 0;
1369 }
1370
1371 void eDVBChannel::stopFile()
1372 {
1373         if (m_pvr_thread)
1374         {
1375                 m_pvr_thread->stop();
1376                 ::close(m_pvr_fd_dst);
1377                 delete m_pvr_thread;
1378                 m_pvr_thread = 0;
1379         }
1380 }
1381
1382 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1383 {
1384         m_conn_cueSheetEvent = 0;
1385         m_cue = cuesheet;
1386         if (m_cue)
1387                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1388 }
1389
1390 RESULT eDVBChannel::getLength(pts_t &len)
1391 {
1392         return m_tstools.calcLen(len);
1393 }
1394
1395 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1396 {
1397         if (!decoding_demux)
1398                 return -1;
1399         
1400         pts_t now;
1401         
1402         int r;
1403         
1404         if (mode == 0) /* demux */
1405         {
1406                 r = decoding_demux->getSTC(now, 0);
1407                 if (r)
1408                 {
1409                         eDebug("demux getSTC failed");
1410                         return -1;
1411                 }
1412         } else
1413                 now = pos; /* fixup supplied */
1414         
1415         off_t off = 0; /* TODO: fixme */
1416         r = m_tstools.fixupPTS(off, now);
1417         if (r)
1418         {
1419                 eDebug("fixup PTS failed");
1420                 return -1;
1421         }
1422         
1423         pos = now;
1424         
1425         return 0;
1426 }
1427
1428 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1429 {
1430                         /* when seeking, we have to ensure that all buffers are flushed.
1431                            there are basically 3 buffers:
1432                            a.) the filepush's internal buffer
1433                            b.) the PVR buffer (before demux)
1434                            c.) the ratebuffer (after demux)
1435                            
1436                            it's important to clear them in the correct order, otherwise
1437                            the ratebuffer (for example) would immediately refill from
1438                            the not-yet-flushed PVR buffer.
1439                         */
1440
1441         m_pvr_thread->pause();
1442                 /* flush internal filepush buffer */
1443         m_pvr_thread->flush();
1444                 /* HACK: flush PVR buffer */
1445         ::ioctl(m_pvr_fd_dst, 0);
1446         
1447                 /* flush ratebuffers (video, audio) */
1448         if (decoding_demux)
1449                 decoding_demux->flush();
1450
1451                 /* demux will also flush all decoder.. */
1452                 /* resume will re-query the SG */
1453         m_pvr_thread->resume();
1454 }
1455
1456 DEFINE_REF(eCueSheet);
1457
1458 eCueSheet::eCueSheet()
1459 {
1460         m_skipmode_ratio = 0;
1461 }
1462
1463 void eCueSheet::seekTo(int relative, const pts_t &pts)
1464 {
1465         m_lock.WrLock();
1466         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1467         m_lock.Unlock();
1468         m_event(evtSeek);
1469 }
1470         
1471 void eCueSheet::clear()
1472 {
1473         m_lock.WrLock();
1474         m_spans.clear();
1475         m_lock.Unlock();
1476 }
1477
1478 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1479 {
1480         m_lock.WrLock();
1481         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1482         m_lock.Unlock();
1483 }
1484
1485 void eCueSheet::commitSpans()
1486 {
1487         m_event(evtSpanChanged);
1488 }
1489
1490 void eCueSheet::setSkipmode(const pts_t &ratio)
1491 {
1492         m_lock.WrLock();
1493         m_skipmode_ratio = ratio;
1494         m_lock.Unlock();
1495         m_event(evtSkipmode);
1496 }
1497
1498 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1499 {
1500         m_decoding_demux = demux;
1501         m_decoder = decoder;
1502 }
1503
1504 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1505 {
1506         connection = new eConnection(this, m_event.connect(event));
1507         return 0;
1508 }