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