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