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