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