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