Merge remote branch 'origin/bug_530_add_dm800se_support'
[enigma2.git] / 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         if ((unsigned int)PyList_Size(list) != m_frontend.size())
324         {
325                 char blasel[256];
326                 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
327                         m_frontend.size(), PyList_Size(list));
328                 PyErr_SetString(PyExc_StandardError, blasel);
329                 return NULL;
330         }
331         int pos=0;
332         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
333         {
334                 ePyObject obj = PyList_GET_ITEM(list, pos++);
335                 if (!i->m_frontend->setSlotInfo(obj))
336                         return NULL;
337         }
338         pos=0;
339         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
340         {
341                 ePyObject obj = PyList_GET_ITEM(list, pos++);
342                 if (!i->m_frontend->setSlotInfo(obj))
343                         return NULL;
344         }
345         Py_RETURN_NONE;
346 }
347
348 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
349 {
350         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
351         ePtr<eDVBRegisteredFrontend> best;
352         int bestval = 0;
353         int foundone = 0;
354
355         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
356         {
357                 int c = i->m_frontend->isCompatibleWith(feparm);
358
359                 if (c)  /* if we have at least one frontend which is compatible with the source, flag this. */
360                         foundone = 1;
361
362                 if (!i->m_inuse)
363                 {
364 //                      eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
365                         if (c > bestval)
366                         {
367                                 bestval = c;
368                                 best = i;
369                         }
370                 }
371 //              else
372 //                      eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
373         }
374
375         if (best)
376         {
377                 fe = new eDVBAllocatedFrontend(best);
378                 return 0;
379         }
380
381         fe = 0;
382
383         if (foundone)
384                 return errAllSourcesBusy;
385         else
386                 return errNoSourceFound;
387 }
388
389 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
390 {
391         int err = errNoSourceFound;
392         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
393                 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
394                 {
395                         // check if another slot linked to this is in use
396                         long tmp;
397                         i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
398                         if ( tmp != -1 )
399                         {
400                                 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
401                                 if (satpos_depends_to_fe->m_inuse)
402                                 {
403                                         eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
404                                         err = errAllSourcesBusy;
405                                         goto alloc_fe_by_id_not_possible;
406                                 }
407                         }
408                         else // check linked tuners
409                         {
410                                 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
411                                 while ( tmp != -1 )
412                                 {
413                                         eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
414                                         if (next->m_inuse)
415                                         {
416                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
417                                                 err = errAllSourcesBusy;
418                                                 goto alloc_fe_by_id_not_possible;
419                                         }
420                                         next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
421                                 }
422                                 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
423                                 while ( tmp != -1 )
424                                 {
425                                         eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
426                                         if (prev->m_inuse)
427                                         {
428                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
429                                                 err = errAllSourcesBusy;
430                                                 goto alloc_fe_by_id_not_possible;
431                                         }
432                                         prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
433                                 }
434                         }
435                         fe = new eDVBAllocatedFrontend(i);
436                         return 0;
437                 }
438 alloc_fe_by_id_not_possible:
439         fe = 0;
440         return err;
441 }
442
443 #define capHoldDecodeReference 64
444
445 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
446 {
447                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
448                    never use the first one unless we need a decoding demux. */
449
450         eDebug("allocate demux");
451         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
452
453         int n=0;
454
455         if (i == m_demux.end())
456                 return -1;
457
458         ePtr<eDVBRegisteredDemux> unused;
459
460         if (m_boxtype == DM800 || m_boxtype == DM500HD || m_boxtype == DM800SE) // dm800 / 500hd
461         {
462                 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
463                 for (; i != m_demux.end(); ++i, ++n)
464                 {
465                         if (!i->m_inuse)
466                         {
467                                 if (!unused)
468                                         unused = i;
469                         }
470                         else
471                         {
472                                 if (fe)
473                                 {
474                                         if (i->m_adapter == fe->m_adapter && 
475                                             i->m_demux->getSource() == fe->m_frontend->getDVBID())
476                                         {
477                                                 demux = new eDVBAllocatedDemux(i);
478                                                 return 0;
479                                         }
480                                 }
481                                 else if (i->m_demux->getSource() == -1) // PVR
482                                 {
483                                         demux = new eDVBAllocatedDemux(i);
484                                         return 0;
485                                 }
486                         }
487                 }
488         }
489         else if (m_boxtype == DM7025) // ATI
490         {
491                 /* FIXME: hardware demux policy */
492                 if (!(cap & iDVBChannel::capDecode))
493                 {
494                         if (m_demux.size() > 2)  /* assumed to be true, otherwise we have lost anyway */
495                         {
496                                 ++i, ++n;
497                                 ++i, ++n;
498                         }
499                 }
500
501                 for (; i != m_demux.end(); ++i, ++n)
502                 {
503                         int is_decode = n < 2;
504
505                         int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
506
507                         if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
508                         {
509                                 if ((cap & iDVBChannel::capDecode) && !is_decode)
510                                         continue;
511                                 unused = i;
512                                 break;
513                         }
514                 }
515         }
516         else if (m_boxtype == DM8000)
517         {
518                 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
519                 for (; i != m_demux.end(); ++i, ++n)
520                 {
521                         if (fe)
522                         {
523                                 if (!i->m_inuse)
524                                 {
525                                         if (!unused)
526                                                 unused = i;
527                                 }
528                                 else if (i->m_adapter == fe->m_adapter &&
529                                     i->m_demux->getSource() == fe->m_frontend->getDVBID())
530                                 {
531                                         demux = new eDVBAllocatedDemux(i);
532                                         return 0;
533                                 }
534                         }
535                         else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...)
536                         {
537                                 if (i->m_inuse) {
538                                         demux = new eDVBAllocatedDemux(i);
539                                         return 0;
540                                 }
541                                 unused = i;
542                         }
543                 }
544         }
545
546         if (unused)
547         {
548                 demux = new eDVBAllocatedDemux(unused);
549                 if (fe)
550                         demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
551                 else
552                         demux->get().setSourcePVR(0);
553                 return 0;
554         }
555
556         eDebug("demux not found");
557         return -1;
558 }
559
560 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
561 {
562         m_list = list;
563         return 0;
564 }
565
566 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
567 {
568         list = m_list;
569         if (list)
570                 return 0;
571         else
572                 return -ENOENT;
573 }
574
575 #define eDebugNoSimulate(x...) \
576         do { \
577                 if (!simulate) \
578                         eDebug(x); \
579         } while(0)
580 //              else \
581 //              { \
582 //                      eDebugNoNewLine("SIMULATE:"); \
583 //                      eDebug(x); \
584 //              } \
585
586
587 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
588 {
589                 /* first, check if a channel is already existing. */
590         std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
591
592         if (!simulate && m_cached_channel)
593         {
594                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
595                 if(channelid==cache_chan->getChannelID())
596                 {
597                         eDebug("use cached_channel");
598                         channel = m_cached_channel;
599                         return 0;
600                 }
601                 m_cached_channel_state_changed_conn.disconnect();
602                 m_cached_channel=0;
603                 m_releaseCachedChannelTimer->stop();
604         }
605
606         eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
607         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
608         {
609                 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
610                 if (i->m_channel_id == channelid)
611                 {
612                         eDebugNoSimulate("found shared channel..");
613                         channel = i->m_channel;
614                         return 0;
615                 }
616         }
617
618         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
619
620         if (!m_list)
621         {
622                 eDebugNoSimulate("no channel list set!");
623                 return errNoChannelList;
624         }
625
626         ePtr<iDVBFrontendParameters> feparm;
627         if (m_list->getChannelFrontendData(channelid, feparm))
628         {
629                 eDebugNoSimulate("channel not found!");
630                 return errChannelNotInList;
631         }
632
633         /* allocate a frontend. */
634
635         ePtr<eDVBAllocatedFrontend> fe;
636
637         int err = allocateFrontend(fe, feparm, simulate);
638         if (err)
639                 return err;
640
641         RESULT res;
642         ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
643
644         res = ch->setChannel(channelid, feparm);
645         if (res)
646         {
647                 channel = 0;
648                 return errChidNotFound;
649         }
650
651         if (simulate)
652                 channel = ch;
653         else
654         {
655                 m_cached_channel = channel = ch;
656                 m_cached_channel_state_changed_conn =
657                         CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
658         }
659
660         return 0;
661 }
662
663 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
664 {
665         int state=0;
666         chan->getState(state);
667         switch (state)
668         {
669                 case iDVBChannel::state_release:
670                 case iDVBChannel::state_ok:
671                 {
672                         eDebug("stop release channel timer");
673                         m_releaseCachedChannelTimer->stop();
674                         break;
675                 }
676                 case iDVBChannel::state_last_instance:
677                 {
678                         eDebug("start release channel timer");
679                         m_releaseCachedChannelTimer->start(3000, true);
680                         break;
681                 }
682                 default: // ignore all other events
683                         break;
684         }
685 }
686
687 void eDVBResourceManager::releaseCachedChannel()
688 {
689         eDebug("release cached channel (timer timeout)");
690         m_cached_channel=0;
691 }
692
693 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
694 {
695         ePtr<eDVBAllocatedFrontend> fe;
696
697         if (m_cached_channel)
698         {
699                 m_cached_channel_state_changed_conn.disconnect();
700                 m_cached_channel=0;
701                 m_releaseCachedChannelTimer->stop();
702         }
703
704         int err = allocateFrontendByIndex(fe, slot_index);
705         if (err)
706                 return err;
707
708         channel = new eDVBChannel(this, fe);
709         return 0;
710 }
711
712
713 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
714 {
715         ePtr<eDVBAllocatedDemux> demux;
716
717         if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
718         {
719                 m_cached_channel_state_changed_conn.disconnect();
720                 m_cached_channel=0;
721                 m_releaseCachedChannelTimer->stop();
722         }
723
724         channel = new eDVBChannel(this, 0);
725         return 0;
726 }
727
728 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
729 {
730         ePtr<iDVBFrontend> fe;
731         if (!ch->getFrontend(fe))
732         {
733                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
734                 if (frontend->is_simulate())
735                         m_active_simulate_channels.push_back(active_channel(chid, ch));
736                 else
737                 {
738                         m_active_channels.push_back(active_channel(chid, ch));
739                         /* emit */ m_channelAdded(ch);
740                 }
741         }
742         return 0;
743 }
744
745 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
746 {
747         ePtr<iDVBFrontend> fe;
748         if (!ch->getFrontend(fe))
749         {
750                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
751                 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
752                 int cnt = 0;
753                 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
754                 {
755                         if (i->m_channel == ch)
756                         {
757                                 i = active_channels.erase(i);
758                                 ++cnt;
759                         } else
760                                 ++i;
761                 }
762                 ASSERT(cnt == 1);
763                 if (cnt == 1)
764                         return 0;
765         }
766         return -ENOENT;
767 }
768
769 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
770 {
771         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
772         return 0;
773 }
774
775 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
776 {
777         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
778         ePtr<eDVBRegisteredFrontend> best;
779         int bestval = 0;
780
781         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
782                 if (!i->m_inuse)
783                 {
784                         int c = i->m_frontend->isCompatibleWith(feparm);
785                         if (c > bestval)
786                                 bestval = c;
787                 }
788         return bestval;
789 }
790
791 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
792 {
793         if (channellist)
794         {
795                 ePtr<iDVBFrontendParameters> feparm;
796                 if (!channellist->getChannelFrontendData(chid, feparm))
797                 {
798                         int system;
799                         if (!feparm->getSystem(system))
800                         {
801                                 switch(system)
802                                 {
803                                         case iDVBFrontend::feSatellite:
804                                                 return 50000;
805                                         case iDVBFrontend::feCable:
806                                                 return 40000;
807                                         case iDVBFrontend::feTerrestrial:
808                                                 return 30000;
809                                         default:
810                                                 break;
811                                 }
812                         }
813                 }
814         }
815         return 0;
816 }
817
818 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
819 {
820         std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
821         int ret=0;
822         if (!simulate && m_cached_channel)
823         {
824                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
825                 if(channelid==cache_chan->getChannelID())
826                         return tuner_type_channel_default(m_list, channelid);
827         }
828
829                 /* first, check if a channel is already existing. */
830 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
831         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
832         {
833 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
834                 if (i->m_channel_id == channelid)
835                 {
836 //                      eDebug("found shared channel..");
837                         return tuner_type_channel_default(m_list, channelid);
838                 }
839         }
840
841         int *decremented_cached_channel_fe_usecount=NULL,
842                 *decremented_fe_usecount=NULL;
843
844         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
845         {
846                 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
847 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
848                 if (i->m_channel_id == ignore)
849                 {
850                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
851                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
852                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
853                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
854                         // or 2 when the cached channel is not equal to the compared channel
855                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
856                         {
857                                 ePtr<iDVBFrontend> fe;
858                                 if (!i->m_channel->getFrontend(fe))
859                                 {
860                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
861                                         {
862                                                 if ( &(*fe) == &(*ii->m_frontend) )
863                                                 {
864                                                         --ii->m_inuse;
865                                                         decremented_fe_usecount = &ii->m_inuse;
866                                                         if (channel == &(*m_cached_channel))
867                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
868                                                         break;
869                                                 }
870                                         }
871                                 }
872                         }
873                         break;
874                 }
875         }
876
877         if (!decremented_cached_channel_fe_usecount)
878         {
879                 if (m_cached_channel)
880                 {
881                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
882                         if (channel->getUseCount() == 1)
883                         {
884                                 ePtr<iDVBFrontend> fe;
885                                 if (!channel->getFrontend(fe))
886                                 {
887                                         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
888                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
889                                         {
890                                                 if ( &(*fe) == &(*ii->m_frontend) )
891                                                 {
892                                                         --ii->m_inuse;
893                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
894                                                         break;
895                                                 }
896                                         }
897                                 }
898                         }
899                 }
900         }
901         else
902                 decremented_cached_channel_fe_usecount=NULL;
903
904         ePtr<iDVBFrontendParameters> feparm;
905
906         if (!m_list)
907         {
908                 eDebug("no channel list set!");
909                 goto error;
910         }
911
912         if (m_list->getChannelFrontendData(channelid, feparm))
913         {
914                 eDebug("channel not found!");
915                 goto error;
916         }
917
918         ret = canAllocateFrontend(feparm, simulate);
919
920 error:
921         if (decremented_fe_usecount)
922                 ++(*decremented_fe_usecount);
923         if (decremented_cached_channel_fe_usecount)
924                 ++(*decremented_cached_channel_fe_usecount);
925
926         return ret;
927 }
928
929 bool eDVBResourceManager::canMeasureFrontendInputPower()
930 {
931         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
932         {
933                 return i->m_frontend->readInputpower() >= 0;
934         }
935         return false;
936 }
937
938 class eDVBChannelFilePush: public eFilePushThread
939 {
940 public:
941         eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
942         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
943
944                         /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
945                         /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
946         void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
947 protected:
948         int m_iframe_search, m_iframe_state, m_pid;
949         int m_timebase_change;
950         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
951 };
952
953 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
954 {
955 #if 0
956         if (m_timebase_change)
957         {
958                 eDebug("timebase change: %d", m_timebase_change);
959                 int offset;
960                 for (offset = 0; offset < len; offset += 188)
961                 {
962                         unsigned char *pkt = (unsigned char*)_data + offset;
963                         if (pkt[1] & 0x40) /* pusi */
964                         {
965                                 if (pkt[3] & 0x20) // adaption field present?
966                                         pkt += pkt[4] + 4 + 1;  /* skip adaption field and header */
967                                 else
968                                         pkt += 4; /* skip header */
969                                 if (pkt[0] || pkt[1] || (pkt[2] != 1))
970                                 {
971                                         eWarning("broken startcode");
972                                         continue;
973                                 }
974
975                                 pts_t pts = 0;
976
977                                 if (pkt[7] & 0x80) // PTS present?
978                                 {
979                                         pts  = ((unsigned long long)(pkt[ 9]&0xE))  << 29;
980                                         pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
981                                         pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
982                                         pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
983                                         pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
984
985 #if 0
986                                         off_t off = 0;
987                                         RESULT r = m_tstools.fixupPTS(off, pts);
988                                         if (r)
989                                                 eWarning("fixup PTS while trickmode playback failed.\n");
990 #endif
991
992                                         int sec = pts / 90000;
993                                         int frm = pts % 90000;
994                                         int min = sec / 60;
995                                         sec %= 60;
996                                         int hr = min / 60;
997                                         min %= 60;
998                                         int d = hr / 24;
999                                         hr %= 24;
1000
1001 //                                      eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1002
1003                                         pts += 0x80000000LL;
1004                                         pts *= m_timebase_change;
1005                                         pts >>= 16;
1006
1007                                         sec = pts / 90000;
1008                                         frm = pts % 90000;
1009                                         min = sec / 60;
1010                                         sec %= 60;
1011                                         hr = min / 60;
1012                                         min %= 60;
1013                                         d = hr / 24;
1014                                         hr %= 24;
1015
1016 //                                      eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1017
1018                                         pkt[9] &= ~0xE;
1019                                         pkt[10] = 0;
1020                                         pkt[11] &= ~1;
1021                                         pkt[12] = 0;
1022                                         pkt[13] &= ~1;
1023
1024                                         pkt[9]  |= (pts >> 29) & 0xE;
1025                                         pkt[10] |= (pts >> 22) & 0xFF;
1026                                         pkt[11] |= (pts >> 14) & 0xFE;
1027                                         pkt[12] |= (pts >> 7) & 0xFF;
1028                                         pkt[13] |= (pts << 1) & 0xFE;
1029                                 }
1030                         }
1031                 }
1032         }
1033 #endif
1034
1035 #if 0
1036         if (!m_iframe_search)
1037                 return len;
1038
1039         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1040
1041 //      eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1042
1043         unsigned char *d = data;
1044         while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1045         {
1046                 int offset = d - data;
1047                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1048                 unsigned char *ts = data + ts_offset;
1049                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1050
1051                 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
1052                 {
1053                         int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1054                         d += 4;
1055
1056 //                      eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1057
1058                         if (m_iframe_state == 1)
1059                         {
1060                                         /* we are allowing data, and stop allowing data on the next frame.
1061                                            we now found a frame. so stop here. */
1062                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1063                                 current_span_remaining = 0;
1064                                 m_iframe_state = 0;
1065                                 unsigned char *fts = ts + 188;
1066                                 while (fts < (data + len))
1067                                 {
1068                                         fts[1] |= 0x1f;
1069                                         fts[2] |= 0xff; /* drop packet */
1070                                         fts += 188;
1071                                 }
1072
1073                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1074                         } else
1075                         {
1076                                 if (picture_type != 1) /* we are only interested in I frames */
1077                                         continue;
1078
1079                                 unsigned char *fts = data;
1080                                 while (fts < ts)
1081                                 {
1082                                         fts[1] |= 0x1f;
1083                                         fts[2] |= 0xff; /* drop packet */
1084
1085                                         fts += 188;
1086                                 }
1087
1088                                 m_iframe_state = 1;
1089                         }
1090                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1091                 {
1092                                 /* verify that this is actually a PES header, not just some ES data */
1093                         if (ts[1] & 0x40) /* PUSI set */
1094                         {
1095                                 int payload_start = 4;
1096                                 if (ts[3] & 0x20) /* adaptation field present */
1097                                         payload_start += ts[4] + 1; /* skip AF */
1098                                 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1099                                 {
1100                                         if (m_pid != pid)
1101                                         {
1102                                                 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1103                                                 m_pid = pid;
1104                                         }
1105                                 }
1106                         }
1107 //                      m_pid = 0x6e;
1108                         d += 4;
1109                 } else
1110                         d += 4; /* ignore */
1111         }
1112
1113         if (m_iframe_state == 1)
1114                 return len;
1115         else
1116                 return 0; /* we need find an iframe first */
1117 #else
1118         return len;
1119 #endif
1120 }
1121
1122 DEFINE_REF(eDVBChannel);
1123
1124 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1125 {
1126         m_frontend = frontend;
1127
1128         m_pvr_thread = 0;
1129         m_pvr_fd_dst = -1;
1130
1131         m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1132
1133         if (m_frontend)
1134                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1135 }
1136
1137 eDVBChannel::~eDVBChannel()
1138 {
1139         if (m_channel_id)
1140                 m_mgr->removeChannel(this);
1141
1142         stopFile();
1143 }
1144
1145 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1146 {
1147         int state, ourstate = 0;
1148
1149                 /* if we are already in shutdown, don't change state. */
1150         if (m_state == state_release)
1151                 return;
1152
1153         if (fe->getState(state))
1154                 return;
1155
1156         if (state == iDVBFrontend::stateLock)
1157         {
1158                 eDebug("OURSTATE: ok");
1159                 ourstate = state_ok;
1160         } else if (state == iDVBFrontend::stateTuning)
1161         {
1162                 eDebug("OURSTATE: tuning");
1163                 ourstate = state_tuning;
1164         } else if (state == iDVBFrontend::stateLostLock)
1165         {
1166                         /* on managed channels, we try to retune in order to re-acquire lock. */
1167                 if (m_current_frontend_parameters)
1168                 {
1169                         eDebug("OURSTATE: lost lock, trying to retune");
1170                         ourstate = state_tuning;
1171                         m_frontend->get().tune(*m_current_frontend_parameters);
1172                 } else
1173                         /* on unmanaged channels, we don't do this. the client will do this. */
1174                 {
1175                         eDebug("OURSTATE: lost lock, unavailable now.");
1176                         ourstate = state_unavailable;
1177                 }
1178         } else if (state == iDVBFrontend::stateFailed)
1179         {
1180                 eDebug("OURSTATE: failed");
1181                 ourstate = state_failed;
1182         } else
1183                 eFatal("state unknown");
1184
1185         if (ourstate != m_state)
1186         {
1187                 m_state = ourstate;
1188                 m_stateChanged(this);
1189         }
1190 }
1191
1192 void eDVBChannel::pvrEvent(int event)
1193 {
1194         switch (event)
1195         {
1196         case eFilePushThread::evtEOF:
1197                 eDebug("eDVBChannel: End of file!");
1198                 m_event(this, evtEOF);
1199                 break;
1200         case eFilePushThread::evtUser: /* start */
1201                 eDebug("SOF");
1202                 m_event(this, evtSOF);
1203                 break;
1204         }
1205 }
1206
1207 void eDVBChannel::cueSheetEvent(int event)
1208 {
1209                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1210         if (!m_pvr_thread)
1211                 return;
1212         switch (event)
1213         {
1214         case eCueSheet::evtSeek:
1215                 eDebug("seek.");
1216                 flushPVR(m_cue->m_decoding_demux);
1217                 break;
1218         case eCueSheet::evtSkipmode:
1219         {
1220                 {
1221                         m_cue->m_lock.WrLock();
1222                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1223                         m_cue->m_lock.Unlock();
1224                         eRdLocker l(m_cue->m_lock);
1225                         if (m_cue->m_skipmode_ratio)
1226                         {
1227                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1228                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1229                                                 /* i agree that this might look a bit like black magic. */
1230                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1231                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1232                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1233                                 m_skipmode_frames_remainder = 0;
1234
1235                                 if (m_cue->m_skipmode_ratio < 0)
1236                                         m_skipmode_m -= m_skipmode_n;
1237
1238                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1239
1240                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1241                                 {
1242                                         eWarning("something is wrong with this calculation");
1243                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1244                                 }
1245                         } else
1246                         {
1247                                 eDebug("skipmode ratio is 0, normal play");
1248                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1249                         }
1250                 }
1251                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1252                 if (m_cue->m_skipmode_ratio != 0)
1253                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1254                 else
1255                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1256                 eDebug("flush pvr");
1257                 flushPVR(m_cue->m_decoding_demux);
1258                 eDebug("done");
1259                 break;
1260         }
1261         case eCueSheet::evtSpanChanged:
1262         {
1263                 m_source_span.clear();
1264                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1265                 {
1266                         off_t offset_in, offset_out;
1267                         pts_t pts_in = i->first, pts_out = i->second;
1268                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1269                         {
1270                                 eDebug("span translation failed.\n");
1271                                 continue;
1272                         }
1273                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1274                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1275                 }
1276                 break;
1277         }
1278         }
1279 }
1280
1281         /* align toward zero */
1282 static inline long long align(long long x, int align)
1283 {
1284         int sign = x < 0;
1285
1286         if (sign)
1287                 x = -x;
1288
1289         x -= x % align;
1290
1291         if (sign)
1292                 x = -x;
1293
1294         return x;
1295 }
1296
1297         /* align toward zero */
1298 static inline long long align_with_len(long long x, int align, size_t &len)
1299 {
1300         int sign = x < 0;
1301
1302         if (sign)
1303                 x = -x;
1304
1305         x -= x % align;
1306         len += x % align;
1307
1308         if (sign)
1309                 x = -x;
1310
1311         return x;
1312 }
1313
1314         /* remember, this gets called from another thread. */
1315 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1316 {
1317         const int blocksize = 188;
1318         unsigned int max = align(10*1024*1024, blocksize);
1319         current_offset = align(current_offset, blocksize);
1320
1321         if (!m_cue)
1322         {
1323                 eDebug("no cue sheet. forcing normal play");
1324                 start = current_offset;
1325                 size = max;
1326                 return;
1327         }
1328
1329         if (m_skipmode_n)
1330         {
1331                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1332                 max = align(m_skipmode_n, blocksize);
1333         }
1334
1335         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1336         int frame_skip_success = 0;
1337
1338         if (m_skipmode_m)
1339         {
1340                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1341                 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1342                 size_t iframe_len;
1343                 off_t iframe_start = current_offset;
1344                 int frames_skipped = frames_to_skip;
1345                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1346                 {
1347                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1348                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1349                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1350                         max = align(iframe_len + 187, blocksize);
1351                         frame_skip_success = 1;
1352                 } else
1353                 {
1354                         m_skipmode_frames_remainder = 0;
1355                         eDebug("frame skipping failed, reverting to byte-skipping");
1356                 }
1357         }
1358         
1359         if (!frame_skip_success)
1360         {
1361                 current_offset += align(m_skipmode_m, blocksize);
1362                 
1363                 if (m_skipmode_m)
1364                 {
1365                         eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1366                         size_t iframe_len;
1367                         off_t iframe_start = current_offset;
1368                         
1369                         int direction = (m_skipmode_m < 0) ? -1 : +1;
1370                         if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1371                                 eDebug("failed");
1372                         else
1373                         {
1374                                 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1375                                 max = align(iframe_len, blocksize);
1376                         }
1377                 }
1378         }
1379
1380         m_cue->m_lock.RdLock();
1381
1382         while (!m_cue->m_seek_requests.empty())
1383         {
1384                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1385                 m_cue->m_lock.Unlock();
1386                 m_cue->m_lock.WrLock();
1387                 m_cue->m_seek_requests.pop_front();
1388                 m_cue->m_lock.Unlock();
1389                 m_cue->m_lock.RdLock();
1390                 int relative = seek.first;
1391                 pts_t pts = seek.second;
1392
1393                 pts_t now = 0;
1394                 if (relative)
1395                 {
1396                         if (!m_cue->m_decoder)
1397                         {
1398                                 eDebug("no decoder - can't seek relative");
1399                                 continue;
1400                         }
1401                         if (m_cue->m_decoder->getPTS(0, now))
1402                         {
1403                                 eDebug("decoder getPTS failed, can't seek relative");
1404                                 continue;
1405                         }
1406                         if (!m_cue->m_decoding_demux)
1407                         {
1408                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1409                                 start = current_offset;
1410                                 size = max;
1411                                 continue;
1412                         }
1413                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1414                         {
1415                                 eDebug("seekTo: getCurrentPosition failed!");
1416                                 continue;
1417                         }
1418                 } else if (pts < 0) /* seek relative to end */
1419                 {
1420                         pts_t len;
1421                         if (!getLength(len))
1422                         {
1423                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1424                                 pts += len;
1425                         } else
1426                         {
1427                                 eWarning("getLength failed - can't seek relative to end!");
1428                                 continue;
1429                         }
1430                 }
1431
1432                 if (relative == 1) /* pts relative */
1433                 {
1434                         pts += now;
1435                         if (pts < 0)
1436                                 pts = 0;
1437                 }
1438
1439                 if (relative != 2)
1440                         if (pts < 0)
1441                                 pts = 0;
1442
1443                 if (relative == 2) /* AP relative */
1444                 {
1445                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1446                         pts_t nextap;
1447                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1448                         {
1449                                 pts = now - 90000; /* approx. 1s */
1450                                 eDebug("AP relative seeking failed!");
1451                         } else
1452                         {
1453                                 pts = nextap;
1454                                 eDebug("next ap is %llx\n", pts);
1455                         }
1456                 }
1457
1458                 off_t offset = 0;
1459                 if (m_tstools.getOffset(offset, pts, -1))
1460                 {
1461                         eDebug("get offset for pts=%lld failed!", pts);
1462                         continue;
1463                 }
1464                 
1465                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
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 int eDVBChannel::reserveDemux()
1663 {
1664         ePtr<iDVBDemux> dmx;
1665         if (!getDemux(dmx, 0))
1666         {
1667                 uint8_t id;
1668                 if (!dmx->getCADemuxID(id))
1669                         return id;
1670         }
1671         return -1;
1672 }
1673
1674 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1675 {
1676         if (PyCallable_Check(callback))
1677         {
1678                 if (!getDemux(m_tsid_onid_demux, 0))
1679                 {
1680                         m_SDT = new eTable<ServiceDescriptionSection>;
1681                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1682                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1683                         {
1684                                 m_tsid_onid_demux = 0;
1685                                 m_SDT = 0;
1686                         }
1687                         else
1688                         {
1689                                 Py_INCREF(callback);
1690                                 m_tsid_onid_callback = callback;
1691                                 return 0;
1692                         }
1693                 }
1694         }
1695         return -1;
1696 }
1697
1698 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1699 {
1700         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1701
1702         if (!our_demux)
1703         {
1704                 demux = 0;
1705
1706                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1707                         return -1;
1708
1709                 demux = *our_demux;
1710
1711                 /* don't hold a reference to the decoding demux, we don't need it. */
1712
1713                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1714                    the refcount is lost. thus, decoding demuxes are never allocated.
1715
1716                    this poses a big problem for PiP. */
1717
1718                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1719                         ;
1720                 else if (cap & capDecode)
1721                         our_demux = 0;
1722         }
1723         else
1724                 demux = *our_demux;
1725
1726         return 0;
1727 }
1728
1729 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1730 {
1731         frontend = 0;
1732         if (!m_frontend)
1733                 return -ENODEV;
1734         frontend = &m_frontend->get();
1735         if (frontend)
1736                 return 0;
1737         return -ENODEV;
1738 }
1739
1740 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1741 {
1742         param = m_current_frontend_parameters;
1743         return 0;
1744 }
1745
1746 RESULT eDVBChannel::playFile(const char *file)
1747 {
1748         ASSERT(!m_frontend);
1749         if (m_pvr_thread)
1750         {
1751                 m_pvr_thread->stop();
1752                 delete m_pvr_thread;
1753                 m_pvr_thread = 0;
1754         }
1755
1756         m_tstools.openFile(file);
1757
1758                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1759                    THEN DO A REAL FIX HERE! */
1760
1761         if (m_pvr_fd_dst < 0)
1762         {
1763                 /* (this codepath needs to be improved anyway.) */
1764 #if HAVE_DVB_API_VERSION < 3
1765                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1766 #else
1767                 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1768 #endif
1769                 if (m_pvr_fd_dst < 0)
1770                 {
1771                         eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1772                         return -ENODEV;
1773                 }
1774         }
1775
1776         m_pvr_thread = new eDVBChannelFilePush();
1777         m_pvr_thread->enablePVRCommit(1);
1778         m_pvr_thread->setStreamMode(1);
1779         m_pvr_thread->setScatterGather(this);
1780
1781         m_event(this, evtPreStart);
1782
1783         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1784         {
1785                 delete m_pvr_thread;
1786                 m_pvr_thread = 0;
1787                 ::close(m_pvr_fd_dst);
1788                 m_pvr_fd_dst = -1;
1789                 eDebug("can't open PVR file %s (%m)", file);
1790                 return -ENOENT;
1791         }
1792         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1793
1794         m_state = state_ok;
1795         m_stateChanged(this);
1796
1797         return 0;
1798 }
1799
1800 void eDVBChannel::stopFile()
1801 {
1802         if (m_pvr_thread)
1803         {
1804                 m_pvr_thread->stop();
1805                 delete m_pvr_thread;
1806                 m_pvr_thread = 0;
1807         }
1808         if (m_pvr_fd_dst >= 0)
1809                 ::close(m_pvr_fd_dst);
1810 }
1811
1812 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1813 {
1814         m_conn_cueSheetEvent = 0;
1815         m_cue = cuesheet;
1816         if (m_cue)
1817                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1818 }
1819
1820 RESULT eDVBChannel::getLength(pts_t &len)
1821 {
1822         return m_tstools.calcLen(len);
1823 }
1824
1825 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1826 {
1827         if (!decoding_demux)
1828                 return -1;
1829
1830         pts_t now;
1831
1832         int r;
1833
1834         if (mode == 0) /* demux */
1835         {
1836                 r = decoding_demux->getSTC(now, 0);
1837                 if (r)
1838                 {
1839                         eDebug("demux getSTC failed");
1840                         return -1;
1841                 }
1842         } else
1843                 now = pos; /* fixup supplied */
1844
1845         off_t off = 0; /* TODO: fixme */
1846         r = m_tstools.fixupPTS(off, now);
1847         if (r)
1848         {
1849                 eDebug("fixup PTS failed");
1850                 return -1;
1851         }
1852
1853         pos = now;
1854
1855         return 0;
1856 }
1857
1858 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1859 {
1860                         /* when seeking, we have to ensure that all buffers are flushed.
1861                            there are basically 3 buffers:
1862                            a.) the filepush's internal buffer
1863                            b.) the PVR buffer (before demux)
1864                            c.) the ratebuffer (after demux)
1865
1866                            it's important to clear them in the correct order, otherwise
1867                            the ratebuffer (for example) would immediately refill from
1868                            the not-yet-flushed PVR buffer.
1869                         */
1870
1871         m_pvr_thread->pause();
1872                 /* flush internal filepush buffer */
1873         m_pvr_thread->flush();
1874                 /* HACK: flush PVR buffer */
1875         ::ioctl(m_pvr_fd_dst, 0);
1876
1877                 /* flush ratebuffers (video, audio) */
1878         if (decoding_demux)
1879                 decoding_demux->flush();
1880
1881                 /* demux will also flush all decoder.. */
1882                 /* resume will re-query the SG */
1883         m_pvr_thread->resume();
1884 }
1885
1886 DEFINE_REF(eCueSheet);
1887
1888 eCueSheet::eCueSheet()
1889 {
1890         m_skipmode_ratio = 0;
1891 }
1892
1893 void eCueSheet::seekTo(int relative, const pts_t &pts)
1894 {
1895         m_lock.WrLock();
1896         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1897         m_lock.Unlock();
1898         m_event(evtSeek);
1899 }
1900
1901 void eCueSheet::clear()
1902 {
1903         m_lock.WrLock();
1904         m_spans.clear();
1905         m_lock.Unlock();
1906 }
1907
1908 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1909 {
1910         ASSERT(begin < end);
1911         m_lock.WrLock();
1912         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1913         m_lock.Unlock();
1914 }
1915
1916 void eCueSheet::commitSpans()
1917 {
1918         m_event(evtSpanChanged);
1919 }
1920
1921 void eCueSheet::setSkipmode(const pts_t &ratio)
1922 {
1923         m_lock.WrLock();
1924         m_skipmode_ratio = ratio;
1925         m_lock.Unlock();
1926         m_event(evtSkipmode);
1927 }
1928
1929 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1930 {
1931         m_decoding_demux = demux;
1932         m_decoder = decoder;
1933 }
1934
1935 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1936 {
1937         connection = new eConnection(this, m_event.connect(event));
1938         return 0;
1939 }