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