rework decoder states
[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 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */
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 + 3 < data + len) && (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 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
993                 {
994                         int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
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                                 /* verify that this is actually a PES header, not just some ES data */
1039                         if (ts[1] & 0x40) /* PUSI set */
1040                         {
1041                                 int payload_start = 4;
1042                                 if (ts[3] & 0x20) /* adaptation field present */
1043                                         payload_start += ts[4] + 1; /* skip AF */
1044                                 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1045                                 {
1046                                         if (m_pid != pid)
1047                                         {
1048                                                 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1049                                                 m_pid = pid;
1050                                         }
1051                                 }
1052                         }
1053 //                      m_pid = 0x6e;
1054                         d += 4;
1055                 } else
1056                         d += 4; /* ignore */
1057         }
1058
1059         if (m_iframe_state == 1)
1060                 return len;
1061         else
1062                 return 0; /* we need find an iframe first */
1063 #else
1064         return len;
1065 #endif
1066 }
1067
1068 DEFINE_REF(eDVBChannel);
1069
1070 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1071 {
1072         m_frontend = frontend;
1073
1074         m_pvr_thread = 0;
1075         
1076         m_skipmode_n = m_skipmode_m = 0;
1077         
1078         if (m_frontend)
1079                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1080 }
1081
1082 eDVBChannel::~eDVBChannel()
1083 {
1084         if (m_channel_id)
1085                 m_mgr->removeChannel(this);
1086
1087         stopFile();
1088 }
1089
1090 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1091 {
1092         int state, ourstate = 0;
1093         
1094                 /* if we are already in shutdown, don't change state. */
1095         if (m_state == state_release)
1096                 return;
1097         
1098         if (fe->getState(state))
1099                 return;
1100         
1101         if (state == iDVBFrontend::stateLock)
1102         {
1103                 eDebug("OURSTATE: ok");
1104                 ourstate = state_ok;
1105         } else if (state == iDVBFrontend::stateTuning)
1106         {
1107                 eDebug("OURSTATE: tuning");
1108                 ourstate = state_tuning;
1109         } else if (state == iDVBFrontend::stateLostLock)
1110         {
1111                         /* on managed channels, we try to retune in order to re-acquire lock. */
1112                 if (m_current_frontend_parameters)
1113                 {
1114                         eDebug("OURSTATE: lost lock, trying to retune");
1115                         ourstate = state_tuning;
1116                         m_frontend->get().tune(*m_current_frontend_parameters);
1117                 } else
1118                         /* on unmanaged channels, we don't do this. the client will do this. */
1119                 {
1120                         eDebug("OURSTATE: lost lock, unavailable now.");
1121                         ourstate = state_unavailable;
1122                 }
1123         } else if (state == iDVBFrontend::stateFailed)
1124         {
1125                 eDebug("OURSTATE: failed");
1126                 ourstate = state_failed;
1127         } else
1128                 eFatal("state unknown");
1129         
1130         if (ourstate != m_state)
1131         {
1132                 m_state = ourstate;
1133                 m_stateChanged(this);
1134         }
1135 }
1136
1137 void eDVBChannel::pvrEvent(int event)
1138 {
1139         switch (event)
1140         {
1141         case eFilePushThread::evtEOF:
1142                 eDebug("eDVBChannel: End of file!");
1143                 m_event(this, evtEOF);
1144                 break;
1145         case eFilePushThread::evtUser: /* start */
1146                 eDebug("SOF");
1147                 m_event(this, evtSOF);
1148                 break;
1149         }
1150 }
1151
1152 void eDVBChannel::cueSheetEvent(int event)
1153 {
1154                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1155         if (!m_pvr_thread)
1156                 return;
1157         switch (event)
1158         {
1159         case eCueSheet::evtSeek:
1160                 eDebug("seek.");
1161                 flushPVR(m_cue->m_decoding_demux);
1162                 break;
1163         case eCueSheet::evtSkipmode:
1164         {
1165                 {
1166                         m_cue->m_lock.WrLock();
1167                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1168                         m_cue->m_lock.Unlock();
1169                         eRdLocker l(m_cue->m_lock);
1170                         if (m_cue->m_skipmode_ratio)
1171                         {
1172                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1173                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1174                                                 /* i agree that this might look a bit like black magic. */
1175                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1176                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1177
1178                                 if (m_cue->m_skipmode_ratio < 0)
1179                                         m_skipmode_m -= m_skipmode_n;
1180
1181                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1182
1183                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1184                                 {
1185                                         eWarning("something is wrong with this calculation");
1186                                         m_skipmode_n = m_skipmode_m = 0;
1187                                 }
1188                         } else
1189                         {
1190                                 eDebug("skipmode ratio is 0, normal play");
1191                                 m_skipmode_n = m_skipmode_m = 0;
1192                         }
1193                 }
1194                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1195                 if (m_cue->m_skipmode_ratio != 0)
1196                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1197                 else
1198                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1199                 eDebug("flush pvr");
1200                 flushPVR(m_cue->m_decoding_demux);
1201                 eDebug("done");
1202                 break;
1203         }
1204         case eCueSheet::evtSpanChanged:
1205         {
1206                 m_source_span.clear();
1207                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1208                 {
1209                         off_t offset_in, offset_out;
1210                         pts_t pts_in = i->first, pts_out = i->second;
1211                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1212                         {
1213                                 eDebug("span translation failed.\n");
1214                                 continue;
1215                         }
1216                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1217                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1218                 }
1219                 break;
1220         }
1221         }
1222 }
1223
1224         /* align toward zero */
1225 static inline long long align(long long x, int align)
1226 {
1227         int sign = x < 0;
1228
1229         if (sign)
1230                 x = -x;
1231
1232         x -= x % align;
1233
1234         if (sign)
1235                 x = -x;
1236
1237         return x;
1238 }
1239
1240         /* remember, this gets called from another thread. */
1241 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1242 {
1243         const int blocksize = 188;
1244         unsigned int max = align(10*1024*1024, blocksize);
1245         current_offset = align(current_offset, blocksize);
1246         
1247         if (!m_cue)
1248         {
1249                 eDebug("no cue sheet. forcing normal play");
1250                 start = current_offset;
1251                 size = max;
1252                 return;
1253         }
1254
1255         m_cue->m_lock.RdLock();
1256         if (!m_cue->m_decoding_demux)
1257         {
1258                 start = current_offset;
1259                 size = max;
1260                 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1261                 m_cue->m_lock.Unlock();
1262                 return;
1263         }
1264
1265         if (m_skipmode_n)
1266         {
1267                 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1268                 max = align(m_skipmode_n, blocksize);
1269         }
1270
1271         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1272
1273         current_offset += align(m_skipmode_m, blocksize);
1274
1275         while (!m_cue->m_seek_requests.empty())
1276         {
1277                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1278                 m_cue->m_lock.Unlock();
1279                 m_cue->m_lock.WrLock();
1280                 m_cue->m_seek_requests.pop_front();
1281                 m_cue->m_lock.Unlock();
1282                 m_cue->m_lock.RdLock();
1283                 int relative = seek.first;
1284                 pts_t pts = seek.second;
1285
1286                 pts_t now = 0;
1287                 if (relative)
1288                 {
1289                         if (!m_cue->m_decoder)
1290                         {
1291                                 eDebug("no decoder - can't seek relative");
1292                                 continue;
1293                         }
1294                         if (m_cue->m_decoder->getPTS(0, now))
1295                         {
1296                                 eDebug("decoder getPTS failed, can't seek relative");
1297                                 continue;
1298                         }
1299                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1300                         {
1301                                 eDebug("seekTo: getCurrentPosition failed!");
1302                                 continue;
1303                         }
1304                 } else if (pts < 0) /* seek relative to end */
1305                 {
1306                         pts_t len;
1307                         if (!getLength(len))
1308                         {
1309                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1310                                 pts += len;
1311                         } else
1312                         {
1313                                 eWarning("getLength failed - can't seek relative to end!");
1314                                 continue;
1315                         }
1316                 }
1317                 
1318                 if (relative == 1) /* pts relative */
1319                 {
1320                         pts += now;
1321                         if (pts < 0)
1322                                 pts = 0;
1323                 }
1324
1325                 if (relative != 2)
1326                         if (pts < 0)
1327                                 pts = 0;
1328                 
1329                 if (relative == 2) /* AP relative */
1330                 {
1331                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1332                         pts_t nextap;
1333                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1334                         {
1335                                 pts = now - 90000; /* approx. 1s */
1336                                 eDebug("AP relative seeking failed!");
1337                         } else
1338                         {
1339                                 pts = nextap;
1340                                 eDebug("next ap is %llx\n", pts);
1341                         }
1342                 }
1343                 
1344                 off_t offset = 0;
1345                 if (m_tstools.getOffset(offset, pts, -1))
1346                 {
1347                         eDebug("get offset for pts=%lld failed!", pts);
1348                         continue;
1349                 }
1350
1351                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1352                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1353         }
1354
1355         m_cue->m_lock.Unlock();
1356
1357         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1358         {
1359                 long long aligned_start = align(i->first, blocksize);
1360                 long long aligned_end = align(i->second, blocksize);
1361         
1362                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1363                 {
1364                         start = current_offset;
1365                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1366                         if ((aligned_end - current_offset) > max)
1367                                 size = max;
1368                         else
1369                                 size = aligned_end - current_offset;
1370                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1371                         return;
1372                 }
1373                 if (current_offset < aligned_start)
1374                 {
1375                                 /* ok, our current offset is in an 'out' zone. */
1376                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1377                         {
1378                                         /* in normal playback, just start at the next zone. */
1379                                 start = i->first;
1380
1381                                         /* size is not 64bit! */
1382                                 if ((i->second - i->first) > max)
1383                                         size = max;
1384                                 else
1385                                         size = aligned_end - aligned_start;
1386
1387                                 eDebug("skip");
1388                                 if (m_skipmode_m < 0)
1389                                 {
1390                                         eDebug("reached SOF");
1391                                                 /* reached SOF */
1392                                         m_skipmode_m = 0;
1393                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1394                                 }
1395                         } else
1396                         {
1397                                         /* when skipping reverse, however, choose the zone before. */
1398                                 --i;
1399                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1400                                 size_t len;
1401
1402                                 aligned_start = align(i->first, blocksize);
1403                                 aligned_end = align(i->second, blocksize);
1404
1405                                 if ((aligned_end - aligned_start) > max)
1406                                         len = max;
1407                                 else
1408                                         len = aligned_end - aligned_start;
1409
1410                                 start = aligned_end - len;
1411                                 eDebug("skipping to %llx, %d", start, len);
1412                         }
1413
1414                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1415                         return;
1416                 }
1417         }
1418
1419         if (m_source_span.empty()) {
1420                 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1421                 {
1422                         eDebug("reached SOF");
1423                         m_skipmode_m = 0;
1424                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1425                 }
1426                 start = current_offset;
1427                 size = max;
1428         } else {
1429                 off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize);
1430                 pts_t len;
1431                 getLength(len);
1432                 m_tstools.getOffset(tmp2, len, 1);
1433                 if (current_offset == tmp || current_offset == tmp2) {
1434                         start = tmp2;
1435                         size = max;
1436                 } else {
1437                         start = tmp - align(512*1024, blocksize);
1438                         size = align(512*1024, blocksize);
1439                 }
1440         }
1441
1442         eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1443         return;
1444 }
1445
1446 void eDVBChannel::AddUse()
1447 {
1448         if (++m_use_count > 1 && m_state == state_last_instance)
1449         {
1450                 m_state = state_ok;
1451                 m_stateChanged(this);
1452         }
1453 }
1454
1455 void eDVBChannel::ReleaseUse()
1456 {
1457         if (!--m_use_count)
1458         {
1459                 m_state = state_release;
1460                 m_stateChanged(this);
1461         }
1462         else if (m_use_count == 1)
1463         {
1464                 m_state = state_last_instance;
1465                 m_stateChanged(this);
1466         }
1467 }
1468
1469 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1470 {
1471         if (m_channel_id)
1472                 m_mgr->removeChannel(this);
1473                 
1474         if (!channelid)
1475                 return 0;
1476
1477         if (!m_frontend)
1478         {
1479                 eDebug("no frontend to tune!");
1480                 return -ENODEV;
1481         }
1482         
1483         m_channel_id = channelid;
1484         m_mgr->addChannel(channelid, this);
1485         m_state = state_tuning;
1486                         /* if tuning fails, shutdown the channel immediately. */
1487         int res;
1488         res = m_frontend->get().tune(*feparm);
1489         m_current_frontend_parameters = feparm;
1490         
1491         if (res)
1492         {
1493                 m_state = state_release;
1494                 m_stateChanged(this);
1495                 return res;
1496         }
1497         
1498         return 0;
1499 }
1500
1501 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1502 {
1503         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1504         return 0;
1505 }
1506
1507 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1508 {
1509         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1510         return 0;
1511 }
1512
1513 RESULT eDVBChannel::getState(int &state)
1514 {
1515         state = m_state;
1516         return 0;
1517 }
1518
1519 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1520 {
1521         return -1;
1522 }
1523
1524 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1525 {
1526         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1527         
1528         if (!our_demux)
1529         {
1530                 demux = 0;
1531                 
1532                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1533                         return -1;
1534         }
1535         
1536         demux = *our_demux;
1537                 /* don't hold a reference to the decoding demux, we don't need it. */
1538                 
1539                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1540                    the refcount is lost. thus, decoding demuxes are never allocated. 
1541                    
1542                    this poses a big problem for PiP. */
1543         if (cap & capDecode)
1544                 our_demux = 0;
1545         return 0;
1546 }
1547
1548 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1549 {
1550         frontend = 0;
1551         if (!m_frontend)
1552                 return -ENODEV;
1553         frontend = &m_frontend->get();
1554         if (frontend)
1555                 return 0;
1556         return -ENODEV;
1557 }
1558
1559 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1560 {
1561         param = m_current_frontend_parameters;
1562         return 0;
1563 }
1564
1565 RESULT eDVBChannel::playFile(const char *file)
1566 {
1567         ASSERT(!m_frontend);
1568         if (m_pvr_thread)
1569         {
1570                 m_pvr_thread->stop();
1571                 delete m_pvr_thread;
1572                 m_pvr_thread = 0;
1573         }
1574         
1575         m_tstools.openFile(file);
1576         
1577                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1578                    THEN DO A REAL FIX HERE! */
1579         
1580                 /* (this codepath needs to be improved anyway.) */
1581 #if HAVE_DVB_API_VERSION < 3
1582         m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1583 #else
1584         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1585 #endif
1586         if (m_pvr_fd_dst < 0)
1587         {
1588                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1589                 return -ENODEV;
1590         }
1591
1592         m_pvr_thread = new eDVBChannelFilePush();
1593         m_pvr_thread->enablePVRCommit(1);
1594         m_pvr_thread->setStreamMode(1);
1595         m_pvr_thread->setScatterGather(this);
1596
1597         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1598         {
1599                 delete m_pvr_thread;
1600                 m_pvr_thread = 0;
1601                 eDebug("can't open PVR file %s (%m)", file);
1602                 return -ENOENT;
1603         }
1604         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1605
1606         m_state = state_ok;
1607         m_stateChanged(this);
1608
1609         return 0;
1610 }
1611
1612 void eDVBChannel::stopFile()
1613 {
1614         if (m_pvr_thread)
1615         {
1616                 m_pvr_thread->stop();
1617                 ::close(m_pvr_fd_dst);
1618                 delete m_pvr_thread;
1619                 m_pvr_thread = 0;
1620         }
1621 }
1622
1623 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1624 {
1625         m_conn_cueSheetEvent = 0;
1626         m_cue = cuesheet;
1627         if (m_cue)
1628                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1629 }
1630
1631 RESULT eDVBChannel::getLength(pts_t &len)
1632 {
1633         return m_tstools.calcLen(len);
1634 }
1635
1636 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1637 {
1638         if (!decoding_demux)
1639                 return -1;
1640         
1641         pts_t now;
1642         
1643         int r;
1644         
1645         if (mode == 0) /* demux */
1646         {
1647                 r = decoding_demux->getSTC(now, 0);
1648                 if (r)
1649                 {
1650                         eDebug("demux getSTC failed");
1651                         return -1;
1652                 }
1653         } else
1654                 now = pos; /* fixup supplied */
1655         
1656         off_t off = 0; /* TODO: fixme */
1657         r = m_tstools.fixupPTS(off, now);
1658         if (r)
1659         {
1660                 eDebug("fixup PTS failed");
1661                 return -1;
1662         }
1663         
1664         pos = now;
1665         
1666         return 0;
1667 }
1668
1669 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1670 {
1671                         /* when seeking, we have to ensure that all buffers are flushed.
1672                            there are basically 3 buffers:
1673                            a.) the filepush's internal buffer
1674                            b.) the PVR buffer (before demux)
1675                            c.) the ratebuffer (after demux)
1676                            
1677                            it's important to clear them in the correct order, otherwise
1678                            the ratebuffer (for example) would immediately refill from
1679                            the not-yet-flushed PVR buffer.
1680                         */
1681
1682         m_pvr_thread->pause();
1683                 /* flush internal filepush buffer */
1684         m_pvr_thread->flush();
1685                 /* HACK: flush PVR buffer */
1686         ::ioctl(m_pvr_fd_dst, 0);
1687         
1688                 /* flush ratebuffers (video, audio) */
1689         if (decoding_demux)
1690                 decoding_demux->flush();
1691
1692                 /* demux will also flush all decoder.. */
1693                 /* resume will re-query the SG */
1694         m_pvr_thread->resume();
1695 }
1696
1697 DEFINE_REF(eCueSheet);
1698
1699 eCueSheet::eCueSheet()
1700 {
1701         m_skipmode_ratio = 0;
1702 }
1703
1704 void eCueSheet::seekTo(int relative, const pts_t &pts)
1705 {
1706         m_lock.WrLock();
1707         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1708         m_lock.Unlock();
1709         m_event(evtSeek);
1710 }
1711         
1712 void eCueSheet::clear()
1713 {
1714         m_lock.WrLock();
1715         m_spans.clear();
1716         m_lock.Unlock();
1717 }
1718
1719 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1720 {
1721         assert(begin < end);
1722         m_lock.WrLock();
1723         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1724         m_lock.Unlock();
1725 }
1726
1727 void eCueSheet::commitSpans()
1728 {
1729         m_event(evtSpanChanged);
1730 }
1731
1732 void eCueSheet::setSkipmode(const pts_t &ratio)
1733 {
1734         m_lock.WrLock();
1735         m_skipmode_ratio = ratio;
1736         m_lock.Unlock();
1737         m_event(evtSkipmode);
1738 }
1739
1740 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1741 {
1742         m_decoding_demux = demux;
1743         m_decoder = decoder;
1744 }
1745
1746 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1747 {
1748         connection = new eConnection(this, m_event.connect(event));
1749         return 0;
1750 }