lock on pids only if video startcode is in a pes header
[vuplus_dvbapp] / 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(eTimer::create(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 = new eDVBChannel(this, fe);
584
585         res = ch->setChannel(channelid, feparm);
586         if (res)
587         {
588                 channel = 0;
589                 return errChidNotFound;
590         }
591
592         if (simulate)
593                 channel = ch;
594         else
595         {
596                 m_cached_channel = channel = ch;
597                 m_cached_channel_state_changed_conn =
598                         CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
599         }
600
601         return 0;
602 }
603
604 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
605 {
606         int state=0;
607         chan->getState(state);
608         switch (state)
609         {
610                 case iDVBChannel::state_release:
611                 case iDVBChannel::state_ok:
612                 {
613                         eDebug("stop release channel timer");
614                         m_releaseCachedChannelTimer->stop();
615                         break;
616                 }
617                 case iDVBChannel::state_last_instance:
618                 {
619                         eDebug("start release channel timer");
620                         m_releaseCachedChannelTimer->start(3000, true);
621                         break;
622                 }
623                 default: // ignore all other events
624                         break;
625         }
626 }
627
628 void eDVBResourceManager::releaseCachedChannel()
629 {
630         eDebug("release cached channel (timer timeout)");
631         m_cached_channel=0;
632 }
633
634 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
635 {
636         ePtr<eDVBAllocatedFrontend> fe;
637
638         if (m_cached_channel)
639         {
640                 m_cached_channel_state_changed_conn.disconnect();
641                 m_cached_channel=0;
642                 m_releaseCachedChannelTimer->stop();
643         }
644
645         int err = allocateFrontendByIndex(fe, slot_index);
646         if (err)
647                 return err;
648
649         channel = new eDVBChannel(this, fe);
650         return 0;
651 }
652
653
654 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
655 {
656         ePtr<eDVBAllocatedDemux> demux;
657
658         if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
659         {
660                 m_cached_channel_state_changed_conn.disconnect();
661                 m_cached_channel=0;
662                 m_releaseCachedChannelTimer->stop();
663         }
664
665         channel = new eDVBChannel(this, 0);
666         return 0;
667 }
668
669 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
670 {
671         ePtr<iDVBFrontend> fe;
672         if (!ch->getFrontend(fe))
673         {
674                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
675                 if (frontend->is_simulate())
676                         m_active_simulate_channels.push_back(active_channel(chid, ch));
677                 else
678                 {
679                         m_active_channels.push_back(active_channel(chid, ch));
680                         /* emit */ m_channelAdded(ch);
681                 }
682         }
683         return 0;
684 }
685
686 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
687 {
688         ePtr<iDVBFrontend> fe;
689         if (!ch->getFrontend(fe))
690         {
691                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
692                 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
693                 int cnt = 0;
694                 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
695                 {
696                         if (i->m_channel == ch)
697                         {
698                                 i = active_channels.erase(i);
699                                 ++cnt;
700                         } else
701                                 ++i;
702                 }
703                 ASSERT(cnt == 1);
704                 if (cnt == 1)
705                         return 0;
706         }
707         return -ENOENT;
708 }
709
710 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
711 {
712         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
713         return 0;
714 }
715
716 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
717 {
718         ePtr<eDVBRegisteredFrontend> best;
719         int bestval = 0;
720
721         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
722                 if (!i->m_inuse)
723                 {
724                         int c = i->m_frontend->isCompatibleWith(feparm);
725                         if (c > bestval)
726                                 bestval = c;
727                 }
728         return bestval;
729 }
730
731 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
732 {
733         if (channellist)
734         {
735                 ePtr<iDVBFrontendParameters> feparm;
736                 if (!channellist->getChannelFrontendData(chid, feparm))
737                 {
738                         int system;
739                         if (!feparm->getSystem(system))
740                         {
741                                 switch(system)
742                                 {
743                                         case iDVBFrontend::feSatellite:
744                                                 return 50000;
745                                         case iDVBFrontend::feCable:
746                                                 return 40000;
747                                         case iDVBFrontend::feTerrestrial:
748                                                 return 30000;
749                                         default:
750                                                 break;
751                                 }
752                         }
753                 }
754         }
755         return 0;
756 }
757
758 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
759 {
760         int ret=0;
761         if (m_cached_channel)
762         {
763                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
764                 if(channelid==cache_chan->getChannelID())
765                         return tuner_type_channel_default(m_list, channelid);
766         }
767
768                 /* first, check if a channel is already existing. */
769 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
770         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
771         {
772 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
773                 if (i->m_channel_id == channelid)
774                 {
775 //                      eDebug("found shared channel..");
776                         return tuner_type_channel_default(m_list, channelid);
777                 }
778         }
779
780         int *decremented_cached_channel_fe_usecount=NULL,
781                 *decremented_fe_usecount=NULL;
782
783         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
784         {
785 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
786                 if (i->m_channel_id == ignore)
787                 {
788                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
789                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
790                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
791                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
792                         // or 2 when the cached channel is not equal to the compared channel
793                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
794                         {
795                                 ePtr<iDVBFrontend> fe;
796                                 if (!i->m_channel->getFrontend(fe))
797                                 {
798                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
799                                         {
800                                                 if ( &(*fe) == &(*ii->m_frontend) )
801                                                 {
802                                                         --ii->m_inuse;
803                                                         decremented_fe_usecount = &ii->m_inuse;
804                                                         if (channel == &(*m_cached_channel))
805                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
806                                                         break;
807                                                 }
808                                         }
809                                 }
810                         }
811                         break;
812                 }
813         }
814
815         if (!decremented_cached_channel_fe_usecount)
816         {
817                 if (m_cached_channel)
818                 {
819                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
820                         if (channel->getUseCount() == 1)
821                         {
822                                 ePtr<iDVBFrontend> fe;
823                                 if (!channel->getFrontend(fe))
824                                 {
825                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
826                                         {
827                                                 if ( &(*fe) == &(*ii->m_frontend) )
828                                                 {
829                                                         --ii->m_inuse;
830                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
831                                                         break;
832                                                 }
833                                         }
834                                 }
835                         }
836                 }
837         }
838         else
839                 decremented_cached_channel_fe_usecount=NULL;
840
841         ePtr<iDVBFrontendParameters> feparm;
842
843         if (!m_list)
844         {
845                 eDebug("no channel list set!");
846                 goto error;
847         }
848
849         if (m_list->getChannelFrontendData(channelid, feparm))
850         {
851                 eDebug("channel not found!");
852                 goto error;
853         }
854
855         ret = canAllocateFrontend(feparm);
856
857 error:
858         if (decremented_fe_usecount)
859                 ++(*decremented_fe_usecount);
860         if (decremented_cached_channel_fe_usecount)
861                 ++(*decremented_cached_channel_fe_usecount);
862
863         return ret;
864 }
865
866 bool eDVBResourceManager::canMeasureFrontendInputPower()
867 {
868         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
869         {
870                 return i->m_frontend->readInputpower() >= 0;
871         }
872         return false;
873 }
874
875 class eDVBChannelFilePush: public eFilePushThread
876 {
877 public:
878         eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
879         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
880
881                         /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
882                         /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
883         void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
884 protected:
885         int m_iframe_search, m_iframe_state, m_pid;
886         int m_timebase_change;
887         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
888 };
889
890 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
891 {
892 #if 0
893         if (m_timebase_change)
894         {
895                 eDebug("timebase change: %d", m_timebase_change);
896                 int offset;
897                 for (offset = 0; offset < len; offset += 188)
898                 {
899                         unsigned char *pkt = (unsigned char*)_data + offset;
900                         if (pkt[1] & 0x40) /* pusi */
901                         {
902                                 if (pkt[3] & 0x20) // adaption field present?
903                                         pkt += pkt[4] + 4 + 1;  /* skip adaption field and header */
904                                 else
905                                         pkt += 4; /* skip header */
906                                 if (pkt[0] || pkt[1] || (pkt[2] != 1))
907                                 {
908                                         eWarning("broken startcode");
909                                         continue;
910                                 }
911
912                                 pts_t pts = 0;
913
914                                 if (pkt[7] & 0x80) // PTS present?
915                                 {
916                                         pts  = ((unsigned long long)(pkt[ 9]&0xE))  << 29;
917                                         pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
918                                         pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
919                                         pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
920                                         pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
921
922 #if 0
923                                         off_t off = 0;
924                                         RESULT r = m_tstools.fixupPTS(off, pts);
925                                         if (r)
926                                                 eWarning("fixup PTS while trickmode playback failed.\n");
927 #endif
928
929                                         int sec = pts / 90000;
930                                         int frm = pts % 90000;
931                                         int min = sec / 60;
932                                         sec %= 60;
933                                         int hr = min / 60;
934                                         min %= 60;
935                                         int d = hr / 24;
936                                         hr %= 24;
937
938 //                                      eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
939
940                                         pts += 0x80000000LL;
941                                         pts *= m_timebase_change;
942                                         pts >>= 16;
943
944                                         sec = pts / 90000;
945                                         frm = pts % 90000;
946                                         min = sec / 60;
947                                         sec %= 60;
948                                         hr = min / 60;
949                                         min %= 60;
950                                         d = hr / 24;
951                                         hr %= 24;
952
953 //                                      eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
954
955                                         pkt[9] &= ~0xE;
956                                         pkt[10] = 0;
957                                         pkt[11] &= ~1;
958                                         pkt[12] = 0;
959                                         pkt[13] &= ~1;
960
961                                         pkt[9]  |= (pts >> 29) & 0xE;
962                                         pkt[10] |= (pts >> 22) & 0xFF;
963                                         pkt[11] |= (pts >> 14) & 0xFE;
964                                         pkt[12] |= (pts >> 7) & 0xFF;
965                                         pkt[13] |= (pts << 1) & 0xFE;
966                                 }
967                         }
968                 }
969         }
970 #endif
971
972 #if 1 /* not yet */
973         if (!m_iframe_search)
974                 return len;
975
976         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
977
978 //      eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
979
980         unsigned char *d = data;
981         while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
982         {
983                 int offset = d - data;
984                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
985                 unsigned char *ts = data + ts_offset;
986                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
987
988                 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
989                 {
990                         int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
991                         d += 4;
992
993 //                      eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
994
995                         if (m_iframe_state == 1)
996                         {
997                                         /* we are allowing data, and stop allowing data on the next frame. 
998                                            we now found a frame. so stop here. */
999                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1000                                 current_span_remaining = 0;
1001                                 m_iframe_state = 0;
1002                                 unsigned char *fts = ts + 188;
1003                                 while (fts < (data + len))
1004                                 {
1005                                         fts[1] |= 0x1f;
1006                                         fts[2] |= 0xff; /* drop packet */
1007                                         fts += 188;
1008                                 }
1009
1010                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1011                         } else
1012                         {
1013                                 if (picture_type != 1) /* we are only interested in I frames */
1014                                         continue;
1015
1016                                 unsigned char *fts = data;
1017                                 while (fts < ts)
1018                                 {
1019                                         fts[1] |= 0x1f;
1020                                         fts[2] |= 0xff; /* drop packet */
1021
1022                                         fts += 188;
1023                                 }
1024                                                 /* force payload only */
1025                                 ts[3] &= ~0x30;
1026                                 ts[3] |=  0x10;
1027
1028 //                              memset(ts + 4, 0xFF, (offset % 188) - 4);
1029
1030                                 m_iframe_state = 1;
1031                         }
1032                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1033                 {
1034                                 /* verify that this is actually a PES header, not just some ES data */
1035                         if (ts[1] & 0x40) /* PUSI set */
1036                         {
1037                                 int payload_start = 4;
1038                                 if (ts[3] & 0x20) /* adaptation field present */
1039                                         payload_start += ts[4] + 1; /* skip AF */
1040                                 if (payload_start == (offset%184)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1041                                 {
1042                                         if (m_pid != pid)
1043                                         {
1044                                                 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1045                                                 m_pid = pid;
1046                                         }
1047                                 }
1048                         }
1049 //                      m_pid = 0x6e;
1050                         d += 4;
1051                 } else
1052                         d += 4; /* ignore */
1053
1054         }
1055
1056         if (m_iframe_state == 1)
1057                 return len;
1058         else
1059                 return 0; /* we need find an iframe first */
1060 #else
1061         return len;
1062 #endif
1063 }
1064
1065 DEFINE_REF(eDVBChannel);
1066
1067 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1068 {
1069         m_frontend = frontend;
1070
1071         m_pvr_thread = 0;
1072         
1073         m_skipmode_n = m_skipmode_m = 0;
1074         
1075         if (m_frontend)
1076                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1077 }
1078
1079 eDVBChannel::~eDVBChannel()
1080 {
1081         if (m_channel_id)
1082                 m_mgr->removeChannel(this);
1083
1084         stopFile();
1085 }
1086
1087 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1088 {
1089         int state, ourstate = 0;
1090         
1091                 /* if we are already in shutdown, don't change state. */
1092         if (m_state == state_release)
1093                 return;
1094         
1095         if (fe->getState(state))
1096                 return;
1097         
1098         if (state == iDVBFrontend::stateLock)
1099         {
1100                 eDebug("OURSTATE: ok");
1101                 ourstate = state_ok;
1102         } else if (state == iDVBFrontend::stateTuning)
1103         {
1104                 eDebug("OURSTATE: tuning");
1105                 ourstate = state_tuning;
1106         } else if (state == iDVBFrontend::stateLostLock)
1107         {
1108                         /* on managed channels, we try to retune in order to re-acquire lock. */
1109                 if (m_current_frontend_parameters)
1110                 {
1111                         eDebug("OURSTATE: lost lock, trying to retune");
1112                         ourstate = state_tuning;
1113                         m_frontend->get().tune(*m_current_frontend_parameters);
1114                 } else
1115                         /* on unmanaged channels, we don't do this. the client will do this. */
1116                 {
1117                         eDebug("OURSTATE: lost lock, unavailable now.");
1118                         ourstate = state_unavailable;
1119                 }
1120         } else if (state == iDVBFrontend::stateFailed)
1121         {
1122                 eDebug("OURSTATE: failed");
1123                 ourstate = state_failed;
1124         } else
1125                 eFatal("state unknown");
1126         
1127         if (ourstate != m_state)
1128         {
1129                 m_state = ourstate;
1130                 m_stateChanged(this);
1131         }
1132 }
1133
1134 void eDVBChannel::pvrEvent(int event)
1135 {
1136         switch (event)
1137         {
1138         case eFilePushThread::evtEOF:
1139                 eDebug("eDVBChannel: End of file!");
1140                 m_event(this, evtEOF);
1141                 break;
1142         case eFilePushThread::evtUser: /* start */
1143                 eDebug("SOF");
1144                 m_event(this, evtSOF);
1145                 break;
1146         }
1147 }
1148
1149 void eDVBChannel::cueSheetEvent(int event)
1150 {
1151                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1152         if (!m_pvr_thread)
1153                 return;
1154         switch (event)
1155         {
1156         case eCueSheet::evtSeek:
1157                 eDebug("seek.");
1158                 flushPVR(m_cue->m_decoding_demux);
1159                 break;
1160         case eCueSheet::evtSkipmode:
1161         {
1162                 {
1163                         m_cue->m_lock.WrLock();
1164                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1165                         m_cue->m_lock.Unlock();
1166                         eRdLocker l(m_cue->m_lock);
1167                         if (m_cue->m_skipmode_ratio)
1168                         {
1169                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1170                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1171                                                 /* i agree that this might look a bit like black magic. */
1172                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1173                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1174
1175                                 if (m_cue->m_skipmode_ratio < 0)
1176                                         m_skipmode_m -= m_skipmode_n;
1177
1178                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1179
1180                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1181                                 {
1182                                         eWarning("something is wrong with this calculation");
1183                                         m_skipmode_n = m_skipmode_m = 0;
1184                                 }
1185                         } else
1186                         {
1187                                 eDebug("skipmode ratio is 0, normal play");
1188                                 m_skipmode_n = m_skipmode_m = 0;
1189                         }
1190                 }
1191                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1192                 if (m_cue->m_skipmode_ratio != 0)
1193                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1194                 else
1195                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1196                 eDebug("flush pvr");
1197                 flushPVR(m_cue->m_decoding_demux);
1198                 eDebug("done");
1199                 break;
1200         }
1201         case eCueSheet::evtSpanChanged:
1202         {
1203                 m_source_span.clear();
1204                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1205                 {
1206                         off_t offset_in, offset_out;
1207                         pts_t pts_in = i->first, pts_out = i->second;
1208                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1209                         {
1210                                 eDebug("span translation failed.\n");
1211                                 continue;
1212                         }
1213                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1214                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1215                 }
1216                 break;
1217         }
1218         }
1219 }
1220
1221         /* align toward zero */
1222 static inline long long align(long long x, int align)
1223 {
1224         int sign = x < 0;
1225
1226         if (sign)
1227                 x = -x;
1228
1229         x -= x % align;
1230
1231         if (sign)
1232                 x = -x;
1233
1234         return x;
1235 }
1236
1237         /* remember, this gets called from another thread. */
1238 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1239 {
1240         const int blocksize = 188;
1241         unsigned int max = align(10*1024*1024, blocksize);
1242         current_offset = align(current_offset, blocksize);
1243         
1244         if (!m_cue)
1245         {
1246                 eDebug("no cue sheet. forcing normal play");
1247                 start = current_offset;
1248                 size = max;
1249                 return;
1250         }
1251
1252         m_cue->m_lock.RdLock();
1253         if (!m_cue->m_decoding_demux)
1254         {
1255                 start = current_offset;
1256                 size = max;
1257                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1258                 m_cue->m_lock.Unlock();
1259                 return;
1260         }
1261
1262         if (m_skipmode_n)
1263         {
1264                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1265                 max = align(m_skipmode_n, blocksize);
1266         }
1267
1268         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1269
1270         current_offset += align(m_skipmode_m, blocksize);
1271
1272         while (!m_cue->m_seek_requests.empty())
1273         {
1274                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1275                 m_cue->m_lock.Unlock();
1276                 m_cue->m_lock.WrLock();
1277                 m_cue->m_seek_requests.pop_front();
1278                 m_cue->m_lock.Unlock();
1279                 m_cue->m_lock.RdLock();
1280                 int relative = seek.first;
1281                 pts_t pts = seek.second;
1282
1283                 pts_t now = 0;
1284                 if (relative)
1285                 {
1286                         if (!m_cue->m_decoder)
1287                         {
1288                                 eDebug("no decoder - can't seek relative");
1289                                 continue;
1290                         }
1291                         if (m_cue->m_decoder->getPTS(0, now))
1292                         {
1293                                 eDebug("decoder getPTS failed, can't seek relative");
1294                                 continue;
1295                         }
1296                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1297                         {
1298                                 eDebug("seekTo: getCurrentPosition failed!");
1299                                 continue;
1300                         }
1301                 } else if (pts < 0) /* seek relative to end */
1302                 {
1303                         pts_t len;
1304                         if (!getLength(len))
1305                         {
1306                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1307                                 pts += len;
1308                         } else
1309                         {
1310                                 eWarning("getLength failed - can't seek relative to end!");
1311                                 continue;
1312                         }
1313                 }
1314                 
1315                 if (relative == 1) /* pts relative */
1316                 {
1317                         pts += now;
1318                         if (pts < 0)
1319                                 pts = 0;
1320                 }
1321
1322                 if (relative != 2)
1323                         if (pts < 0)
1324                                 pts = 0;
1325                 
1326                 if (relative == 2) /* AP relative */
1327                 {
1328                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1329                         pts_t nextap;
1330                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1331                         {
1332                                 pts = now - 90000; /* approx. 1s */
1333                                 eDebug("AP relative seeking failed!");
1334                         } else
1335                         {
1336                                 pts = nextap;
1337                                 eDebug("next ap is %llx\n", pts);
1338                         }
1339                 }
1340                 
1341                 off_t offset = 0;
1342                 if (m_tstools.getOffset(offset, pts, -1))
1343                 {
1344                         eDebug("get offset for pts=%lld failed!", pts);
1345                         continue;
1346                 }
1347
1348                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1349                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1350         }
1351
1352         m_cue->m_lock.Unlock();
1353
1354         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1355         {
1356                 long long aligned_start = align(i->first, blocksize);
1357                 long long aligned_end = align(i->second, blocksize);
1358         
1359                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1360                 {
1361                         start = current_offset;
1362                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1363                         if ((aligned_end - current_offset) > max)
1364                                 size = max;
1365                         else
1366                                 size = aligned_end - current_offset;
1367                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1368                         return;
1369                 }
1370                 if (current_offset < aligned_start)
1371                 {
1372                                 /* ok, our current offset is in an 'out' zone. */
1373                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1374                         {
1375                                         /* in normal playback, just start at the next zone. */
1376                                 start = i->first;
1377
1378                                         /* size is not 64bit! */
1379                                 if ((i->second - i->first) > max)
1380                                         size = max;
1381                                 else
1382                                         size = aligned_end - aligned_start;
1383
1384                                 eDebug("skip");
1385                                 if (m_skipmode_m < 0)
1386                                 {
1387                                         eDebug("reached SOF");
1388                                                 /* reached SOF */
1389                                         m_skipmode_m = 0;
1390                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1391                                 }
1392                         } else
1393                         {
1394                                         /* when skipping reverse, however, choose the zone before. */
1395                                 --i;
1396                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1397                                 size_t len;
1398
1399                                 aligned_start = align(i->first, blocksize);
1400                                 aligned_end = align(i->second, blocksize);
1401
1402                                 if ((aligned_end - aligned_start) > max)
1403                                         len = max;
1404                                 else
1405                                         len = aligned_end - aligned_start;
1406
1407                                 start = aligned_end - len;
1408                                 eDebug("skipping to %llx, %d", start, len);
1409                         }
1410
1411                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1412                         return;
1413                 }
1414         }
1415
1416         if (m_source_span.empty()) {
1417                 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1418                 {
1419                         eDebug("reached SOF");
1420                         m_skipmode_m = 0;
1421                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1422                 }
1423                 start = current_offset;
1424                 size = max;
1425         } else {
1426                 off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize);
1427                 pts_t len;
1428                 getLength(len);
1429                 m_tstools.getOffset(tmp2, len, 1);
1430                 if (current_offset == tmp || current_offset == tmp2) {
1431                         start = tmp2;
1432                         size = max;
1433                 } else {
1434                         start = tmp - align(512*1024, blocksize);
1435                         size = align(512*1024, blocksize);
1436                 }
1437         }
1438
1439         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1440         return;
1441 }
1442
1443 void eDVBChannel::AddUse()
1444 {
1445         if (++m_use_count > 1 && m_state == state_last_instance)
1446         {
1447                 m_state = state_ok;
1448                 m_stateChanged(this);
1449         }
1450 }
1451
1452 void eDVBChannel::ReleaseUse()
1453 {
1454         if (!--m_use_count)
1455         {
1456                 m_state = state_release;
1457                 m_stateChanged(this);
1458         }
1459         else if (m_use_count == 1)
1460         {
1461                 m_state = state_last_instance;
1462                 m_stateChanged(this);
1463         }
1464 }
1465
1466 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1467 {
1468         if (m_channel_id)
1469                 m_mgr->removeChannel(this);
1470                 
1471         if (!channelid)
1472                 return 0;
1473
1474         if (!m_frontend)
1475         {
1476                 eDebug("no frontend to tune!");
1477                 return -ENODEV;
1478         }
1479         
1480         m_channel_id = channelid;
1481         m_mgr->addChannel(channelid, this);
1482         m_state = state_tuning;
1483                         /* if tuning fails, shutdown the channel immediately. */
1484         int res;
1485         res = m_frontend->get().tune(*feparm);
1486         m_current_frontend_parameters = feparm;
1487         
1488         if (res)
1489         {
1490                 m_state = state_release;
1491                 m_stateChanged(this);
1492                 return res;
1493         }
1494         
1495         return 0;
1496 }
1497
1498 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1499 {
1500         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1501         return 0;
1502 }
1503
1504 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1505 {
1506         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1507         return 0;
1508 }
1509
1510 RESULT eDVBChannel::getState(int &state)
1511 {
1512         state = m_state;
1513         return 0;
1514 }
1515
1516 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1517 {
1518         return -1;
1519 }
1520
1521 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1522 {
1523         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1524         
1525         if (!our_demux)
1526         {
1527                 demux = 0;
1528                 
1529                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1530                         return -1;
1531         }
1532         
1533         demux = *our_demux;
1534                 /* don't hold a reference to the decoding demux, we don't need it. */
1535                 
1536                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1537                    the refcount is lost. thus, decoding demuxes are never allocated. 
1538                    
1539                    this poses a big problem for PiP. */
1540         if (cap & capDecode)
1541                 our_demux = 0;
1542         return 0;
1543 }
1544
1545 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1546 {
1547         frontend = 0;
1548         if (!m_frontend)
1549                 return -ENODEV;
1550         frontend = &m_frontend->get();
1551         if (frontend)
1552                 return 0;
1553         return -ENODEV;
1554 }
1555
1556 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1557 {
1558         param = m_current_frontend_parameters;
1559         return 0;
1560 }
1561
1562 RESULT eDVBChannel::playFile(const char *file)
1563 {
1564         ASSERT(!m_frontend);
1565         if (m_pvr_thread)
1566         {
1567                 m_pvr_thread->stop();
1568                 delete m_pvr_thread;
1569                 m_pvr_thread = 0;
1570         }
1571         
1572         m_tstools.openFile(file);
1573         
1574                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1575                    THEN DO A REAL FIX HERE! */
1576         
1577                 /* (this codepath needs to be improved anyway.) */
1578 #if HAVE_DVB_API_VERSION < 3
1579         m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1580 #else
1581         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1582 #endif
1583         if (m_pvr_fd_dst < 0)
1584         {
1585                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1586                 return -ENODEV;
1587         }
1588
1589         m_pvr_thread = new eDVBChannelFilePush();
1590         m_pvr_thread->enablePVRCommit(1);
1591         m_pvr_thread->setStreamMode(1);
1592         m_pvr_thread->setScatterGather(this);
1593
1594         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1595         {
1596                 delete m_pvr_thread;
1597                 m_pvr_thread = 0;
1598                 eDebug("can't open PVR file %s (%m)", file);
1599                 return -ENOENT;
1600         }
1601         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1602
1603         m_state = state_ok;
1604         m_stateChanged(this);
1605
1606         return 0;
1607 }
1608
1609 void eDVBChannel::stopFile()
1610 {
1611         if (m_pvr_thread)
1612         {
1613                 m_pvr_thread->stop();
1614                 ::close(m_pvr_fd_dst);
1615                 delete m_pvr_thread;
1616                 m_pvr_thread = 0;
1617         }
1618 }
1619
1620 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1621 {
1622         m_conn_cueSheetEvent = 0;
1623         m_cue = cuesheet;
1624         if (m_cue)
1625                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1626 }
1627
1628 RESULT eDVBChannel::getLength(pts_t &len)
1629 {
1630         return m_tstools.calcLen(len);
1631 }
1632
1633 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1634 {
1635         if (!decoding_demux)
1636                 return -1;
1637         
1638         pts_t now;
1639         
1640         int r;
1641         
1642         if (mode == 0) /* demux */
1643         {
1644                 r = decoding_demux->getSTC(now, 0);
1645                 if (r)
1646                 {
1647                         eDebug("demux getSTC failed");
1648                         return -1;
1649                 }
1650         } else
1651                 now = pos; /* fixup supplied */
1652         
1653         off_t off = 0; /* TODO: fixme */
1654         r = m_tstools.fixupPTS(off, now);
1655         if (r)
1656         {
1657                 eDebug("fixup PTS failed");
1658                 return -1;
1659         }
1660         
1661         pos = now;
1662         
1663         return 0;
1664 }
1665
1666 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1667 {
1668                         /* when seeking, we have to ensure that all buffers are flushed.
1669                            there are basically 3 buffers:
1670                            a.) the filepush's internal buffer
1671                            b.) the PVR buffer (before demux)
1672                            c.) the ratebuffer (after demux)
1673                            
1674                            it's important to clear them in the correct order, otherwise
1675                            the ratebuffer (for example) would immediately refill from
1676                            the not-yet-flushed PVR buffer.
1677                         */
1678
1679         m_pvr_thread->pause();
1680                 /* flush internal filepush buffer */
1681         m_pvr_thread->flush();
1682                 /* HACK: flush PVR buffer */
1683         ::ioctl(m_pvr_fd_dst, 0);
1684         
1685                 /* flush ratebuffers (video, audio) */
1686         if (decoding_demux)
1687                 decoding_demux->flush();
1688
1689                 /* demux will also flush all decoder.. */
1690                 /* resume will re-query the SG */
1691         m_pvr_thread->resume();
1692 }
1693
1694 DEFINE_REF(eCueSheet);
1695
1696 eCueSheet::eCueSheet()
1697 {
1698         m_skipmode_ratio = 0;
1699 }
1700
1701 void eCueSheet::seekTo(int relative, const pts_t &pts)
1702 {
1703         m_lock.WrLock();
1704         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1705         m_lock.Unlock();
1706         m_event(evtSeek);
1707 }
1708         
1709 void eCueSheet::clear()
1710 {
1711         m_lock.WrLock();
1712         m_spans.clear();
1713         m_lock.Unlock();
1714 }
1715
1716 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1717 {
1718         assert(begin < end);
1719         m_lock.WrLock();
1720         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1721         m_lock.Unlock();
1722 }
1723
1724 void eCueSheet::commitSpans()
1725 {
1726         m_event(evtSpanChanged);
1727 }
1728
1729 void eCueSheet::setSkipmode(const pts_t &ratio)
1730 {
1731         m_lock.WrLock();
1732         m_skipmode_ratio = ratio;
1733         m_lock.Unlock();
1734         m_event(evtSkipmode);
1735 }
1736
1737 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1738 {
1739         m_decoding_demux = demux;
1740         m_decoder = decoder;
1741 }
1742
1743 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1744 {
1745         connection = new eConnection(this, m_event.connect(event));
1746         return 0;
1747 }