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