Merge branch 'vuplus_experimental' of 192.168.102.66:/var/ikseong/repo/enigma2 into...
[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 #ifdef BUILD_VUPLUS /* ikseong  */
1190                 if (m_current_frontend_parameters)
1191                 {
1192                         eDebug("OURSTATE: lost lock, trying to retune");
1193                         ourstate = state_tuning;
1194                         m_frontend->get().tune(*m_current_frontend_parameters);
1195                 } 
1196                 else
1197                 {
1198                         eDebug("OURSTATE: failed");
1199                         ourstate = state_failed;
1200                 }
1201 #else
1202                 eDebug("OURSTATE: failed");
1203                 ourstate = state_failed;
1204 #endif          
1205         } else
1206                 eFatal("state unknown");
1207
1208         if (ourstate != m_state)
1209         {
1210                 m_state = ourstate;
1211                 m_stateChanged(this);
1212         }
1213 }
1214
1215 void eDVBChannel::pvrEvent(int event)
1216 {
1217         switch (event)
1218         {
1219         case eFilePushThread::evtEOF:
1220                 eDebug("eDVBChannel: End of file!");
1221                 m_event(this, evtEOF);
1222                 break;
1223         case eFilePushThread::evtUser: /* start */
1224                 eDebug("SOF");
1225                 m_event(this, evtSOF);
1226                 break;
1227         }
1228 }
1229
1230 void eDVBChannel::cueSheetEvent(int event)
1231 {
1232                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1233         if (!m_pvr_thread)
1234                 return;
1235         switch (event)
1236         {
1237         case eCueSheet::evtSeek:
1238                 eDebug("seek.");
1239                 flushPVR(m_cue->m_decoding_demux);
1240                 break;
1241         case eCueSheet::evtSkipmode:
1242         {
1243                 {
1244                         m_cue->m_lock.WrLock();
1245                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1246                         m_cue->m_lock.Unlock();
1247                         eRdLocker l(m_cue->m_lock);
1248                         if (m_cue->m_skipmode_ratio)
1249                         {
1250                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1251                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1252                                                 /* i agree that this might look a bit like black magic. */
1253                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1254                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1255                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1256                                 m_skipmode_frames_remainder = 0;
1257
1258                                 if (m_cue->m_skipmode_ratio < 0)
1259                                         m_skipmode_m -= m_skipmode_n;
1260
1261                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1262
1263                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1264                                 {
1265                                         eWarning("something is wrong with this calculation");
1266                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1267                                 }
1268                         } else
1269                         {
1270                                 eDebug("skipmode ratio is 0, normal play");
1271                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1272                         }
1273                 }
1274                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1275                 if (m_cue->m_skipmode_ratio != 0)
1276                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1277                 else
1278                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1279                 eDebug("flush pvr");
1280                 flushPVR(m_cue->m_decoding_demux);
1281                 eDebug("done");
1282                 break;
1283         }
1284         case eCueSheet::evtSpanChanged:
1285         {
1286                 m_source_span.clear();
1287                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1288                 {
1289                         off_t offset_in, offset_out;
1290                         pts_t pts_in = i->first, pts_out = i->second;
1291                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1292                         {
1293                                 eDebug("span translation failed.\n");
1294                                 continue;
1295                         }
1296                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1297                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1298                 }
1299                 break;
1300         }
1301         }
1302 }
1303
1304         /* align toward zero */
1305 static inline long long align(long long x, int align)
1306 {
1307         int sign = x < 0;
1308
1309         if (sign)
1310                 x = -x;
1311
1312         x -= x % align;
1313
1314         if (sign)
1315                 x = -x;
1316
1317         return x;
1318 }
1319
1320         /* align toward zero */
1321 static inline long long align_with_len(long long x, int align, size_t &len)
1322 {
1323         int sign = x < 0;
1324
1325         if (sign)
1326                 x = -x;
1327
1328         x -= x % align;
1329         len += x % align;
1330
1331         if (sign)
1332                 x = -x;
1333
1334         return x;
1335 }
1336
1337         /* remember, this gets called from another thread. */
1338 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1339 {
1340         const int blocksize = 188;
1341         unsigned int max = align(10*1024*1024, blocksize);
1342         current_offset = align(current_offset, blocksize);
1343
1344         if (!m_cue)
1345         {
1346                 eDebug("no cue sheet. forcing normal play");
1347                 start = current_offset;
1348                 size = max;
1349                 return;
1350         }
1351
1352         if (m_skipmode_n)
1353         {
1354                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1355                 max = align(m_skipmode_n, blocksize);
1356         }
1357
1358         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1359         int frame_skip_success = 0;
1360
1361         if (m_skipmode_m)
1362         {
1363                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1364                 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1365                 size_t iframe_len;
1366                 off_t iframe_start = current_offset;
1367                 int frames_skipped = frames_to_skip;
1368                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1369                 {
1370                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1371                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1372                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1373                         max = align(iframe_len + 187, blocksize);
1374                         frame_skip_success = 1;
1375                 } else
1376                 {
1377                         m_skipmode_frames_remainder = 0;
1378                         eDebug("frame skipping failed, reverting to byte-skipping");
1379                 }
1380         }
1381         
1382         if (!frame_skip_success)
1383         {
1384                 current_offset += align(m_skipmode_m, blocksize);
1385                 
1386                 if (m_skipmode_m)
1387                 {
1388                         eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1389                         size_t iframe_len;
1390                         off_t iframe_start = current_offset;
1391                         
1392                         int direction = (m_skipmode_m < 0) ? -1 : +1;
1393                         if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1394                                 eDebug("failed");
1395                         else
1396                         {
1397                                 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1398                                 max = align(iframe_len, blocksize);
1399                         }
1400                 }
1401         }
1402
1403         m_cue->m_lock.RdLock();
1404
1405         while (!m_cue->m_seek_requests.empty())
1406         {
1407                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1408                 m_cue->m_lock.Unlock();
1409                 m_cue->m_lock.WrLock();
1410                 m_cue->m_seek_requests.pop_front();
1411                 m_cue->m_lock.Unlock();
1412                 m_cue->m_lock.RdLock();
1413                 int relative = seek.first;
1414                 pts_t pts = seek.second;
1415
1416                 pts_t now = 0;
1417                 if (relative)
1418                 {
1419                         if (!m_cue->m_decoder)
1420                         {
1421                                 eDebug("no decoder - can't seek relative");
1422                                 continue;
1423                         }
1424                         if (m_cue->m_decoder->getPTS(0, now))
1425                         {
1426                                 eDebug("decoder getPTS failed, can't seek relative");
1427                                 continue;
1428                         }
1429                         if (!m_cue->m_decoding_demux)
1430                         {
1431                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1432                                 start = current_offset;
1433                                 size = max;
1434                                 continue;
1435                         }
1436                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1437                         {
1438                                 eDebug("seekTo: getCurrentPosition failed!");
1439                                 continue;
1440                         }
1441                 } else if (pts < 0) /* seek relative to end */
1442                 {
1443                         pts_t len;
1444                         if (!getLength(len))
1445                         {
1446                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1447                                 pts += len;
1448                         } else
1449                         {
1450                                 eWarning("getLength failed - can't seek relative to end!");
1451                                 continue;
1452                         }
1453                 }
1454
1455                 if (relative == 1) /* pts relative */
1456                 {
1457                         pts += now;
1458                         if (pts < 0)
1459                                 pts = 0;
1460                 }
1461
1462                 if (relative != 2)
1463                         if (pts < 0)
1464                                 pts = 0;
1465
1466                 if (relative == 2) /* AP relative */
1467                 {
1468                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1469                         pts_t nextap;
1470                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1471                         {
1472                                 pts = now - 90000; /* approx. 1s */
1473                                 eDebug("AP relative seeking failed!");
1474                         } else
1475                         {
1476                                 pts = nextap;
1477                                 eDebug("next ap is %llx\n", pts);
1478                         }
1479                 }
1480
1481                 off_t offset = 0;
1482                 if (m_tstools.getOffset(offset, pts, -1))
1483                 {
1484                         eDebug("get offset for pts=%lld failed!", pts);
1485                         continue;
1486                 }
1487                 
1488                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1489                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1490         }
1491
1492         m_cue->m_lock.Unlock();
1493
1494         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1495         {
1496                 long long aligned_start = align(i->first, blocksize);
1497                 long long aligned_end = align(i->second, blocksize);
1498
1499                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1500                 {
1501                         start = current_offset;
1502                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1503                         if ((aligned_end - current_offset) > max)
1504                                 size = max;
1505                         else
1506                                 size = aligned_end - current_offset;
1507                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1508                         return;
1509                 }
1510                 if (current_offset < aligned_start)
1511                 {
1512                                 /* ok, our current offset is in an 'out' zone. */
1513                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1514                         {
1515                                         /* in normal playback, just start at the next zone. */
1516                                 start = i->first;
1517
1518                                         /* size is not 64bit! */
1519                                 if ((i->second - i->first) > max)
1520                                         size = max;
1521                                 else
1522                                         size = aligned_end - aligned_start;
1523
1524                                 eDebug("skip");
1525                                 if (m_skipmode_m < 0)
1526                                 {
1527                                         eDebug("reached SOF");
1528                                                 /* reached SOF */
1529                                         m_skipmode_m = 0;
1530                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1531                                 }
1532                         } else
1533                         {
1534                                         /* when skipping reverse, however, choose the zone before. */
1535                                 --i;
1536                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1537                                 size_t len;
1538
1539                                 aligned_start = align(i->first, blocksize);
1540                                 aligned_end = align(i->second, blocksize);
1541
1542                                 if ((aligned_end - aligned_start) > max)
1543                                         len = max;
1544                                 else
1545                                         len = aligned_end - aligned_start;
1546
1547                                 start = aligned_end - len;
1548                                 eDebug("skipping to %llx, %zd", start, len);
1549                         }
1550
1551                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1552                         return;
1553                 }
1554         }
1555
1556         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1557         {
1558                 eDebug("reached SOF");
1559                 m_skipmode_m = 0;
1560                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1561         }
1562
1563         if (m_source_span.empty())
1564         {
1565                 start = current_offset;
1566                 size = max;
1567                 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1568         } else
1569         {
1570                 start = current_offset;
1571                 size = 0;
1572         }
1573         return;
1574 }
1575
1576 void eDVBChannel::AddUse()
1577 {
1578         if (++m_use_count > 1 && m_state == state_last_instance)
1579         {
1580                 m_state = state_ok;
1581                 m_stateChanged(this);
1582         }
1583 }
1584
1585 void eDVBChannel::ReleaseUse()
1586 {
1587         if (!--m_use_count)
1588         {
1589                 m_state = state_release;
1590                 m_stateChanged(this);
1591         }
1592         else if (m_use_count == 1)
1593         {
1594                 m_state = state_last_instance;
1595                 m_stateChanged(this);
1596         }
1597 }
1598
1599 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1600 {
1601         if (m_channel_id)
1602                 m_mgr->removeChannel(this);
1603
1604         if (!channelid)
1605                 return 0;
1606
1607         if (!m_frontend)
1608         {
1609                 eDebug("no frontend to tune!");
1610                 return -ENODEV;
1611         }
1612
1613         m_channel_id = channelid;
1614         m_mgr->addChannel(channelid, this);
1615         m_state = state_tuning;
1616                         /* if tuning fails, shutdown the channel immediately. */
1617         int res;
1618         res = m_frontend->get().tune(*feparm);
1619         m_current_frontend_parameters = feparm;
1620
1621         if (res)
1622         {
1623                 m_state = state_release;
1624                 m_stateChanged(this);
1625                 return res;
1626         }
1627
1628         return 0;
1629 }
1630
1631 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1632 {
1633         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1634         return 0;
1635 }
1636
1637 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1638 {
1639         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1640         return 0;
1641 }
1642
1643 RESULT eDVBChannel::getState(int &state)
1644 {
1645         state = m_state;
1646         return 0;
1647 }
1648
1649 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1650 {
1651         return -1;
1652 }
1653
1654 void eDVBChannel::SDTready(int result)
1655 {
1656         ePyObject args = PyTuple_New(2), ret;
1657         bool ok=false;
1658         if (!result)
1659         {
1660                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1661                 {
1662                         ok = true;
1663                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1664                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1665                         break;
1666                 }
1667         }
1668         if (!ok)
1669         {
1670                 PyTuple_SET_ITEM(args, 0, Py_None);
1671                 PyTuple_SET_ITEM(args, 1, Py_None);
1672                 Py_INCREF(Py_None);
1673                 Py_INCREF(Py_None);
1674         }
1675         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1676         if (ret)
1677                 Py_DECREF(ret);
1678         Py_DECREF(args);
1679         Py_DECREF(m_tsid_onid_callback);
1680         m_tsid_onid_callback = ePyObject();
1681         m_tsid_onid_demux = 0;
1682         m_SDT = 0;
1683 }
1684
1685 int eDVBChannel::reserveDemux()
1686 {
1687         ePtr<iDVBDemux> dmx;
1688         if (!getDemux(dmx, 0))
1689         {
1690                 uint8_t id;
1691                 if (!dmx->getCADemuxID(id))
1692                         return id;
1693         }
1694         return -1;
1695 }
1696
1697 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1698 {
1699         if (PyCallable_Check(callback))
1700         {
1701                 if (!getDemux(m_tsid_onid_demux, 0))
1702                 {
1703                         m_SDT = new eTable<ServiceDescriptionSection>;
1704                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1705                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1706                         {
1707                                 m_tsid_onid_demux = 0;
1708                                 m_SDT = 0;
1709                         }
1710                         else
1711                         {
1712                                 Py_INCREF(callback);
1713                                 m_tsid_onid_callback = callback;
1714                                 return 0;
1715                         }
1716                 }
1717         }
1718         return -1;
1719 }
1720
1721 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1722 {
1723         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1724
1725         if (!our_demux)
1726         {
1727                 demux = 0;
1728
1729                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1730                         return -1;
1731
1732                 demux = *our_demux;
1733
1734                 /* don't hold a reference to the decoding demux, we don't need it. */
1735
1736                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1737                    the refcount is lost. thus, decoding demuxes are never allocated.
1738
1739                    this poses a big problem for PiP. */
1740
1741                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1742                         ;
1743                 else if (cap & capDecode)
1744                         our_demux = 0;
1745         }
1746         else
1747                 demux = *our_demux;
1748
1749         return 0;
1750 }
1751
1752 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1753 {
1754         frontend = 0;
1755         if (!m_frontend)
1756                 return -ENODEV;
1757         frontend = &m_frontend->get();
1758         if (frontend)
1759                 return 0;
1760         return -ENODEV;
1761 }
1762
1763 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1764 {
1765         param = m_current_frontend_parameters;
1766         return 0;
1767 }
1768
1769 RESULT eDVBChannel::playFile(const char *file)
1770 {
1771         eRawFile *f = new eRawFile();
1772         ePtr<iTsSource> source = f;
1773
1774         if (f->open(file) < 0)
1775         {
1776                 eDebug("can't open PVR file %s (%m)", file);
1777                 return -ENOENT;
1778         }
1779
1780         return playSource(source, file);
1781 }
1782
1783 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1784 {
1785         ASSERT(!m_frontend);
1786         if (m_pvr_thread)
1787         {
1788                 m_pvr_thread->stop();
1789                 delete m_pvr_thread;
1790                 m_pvr_thread = 0;
1791         }
1792
1793         if (!source->valid())
1794         {
1795                 eDebug("PVR source is not valid!");
1796                 return -ENOENT;
1797         }
1798
1799         m_tstools.setSource(source, streaminfo_file);
1800
1801                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1802                    THEN DO A REAL FIX HERE! */
1803
1804         if (m_pvr_fd_dst < 0)
1805         {
1806                 /* (this codepath needs to be improved anyway.) */
1807 #if HAVE_DVB_API_VERSION < 3
1808                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1809                 if (m_pvr_fd_dst < 0)
1810                 {
1811                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1812                         return -ENODEV;
1813                 }
1814 #else
1815                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1816                 if (demux)
1817                 {
1818                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1819                         if (m_pvr_fd_dst < 0)
1820                         {
1821                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1822                                 return -ENODEV;
1823                         }
1824                 }
1825                 else
1826                 {
1827                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1828                         return -ENODEV;
1829                 }
1830 #endif
1831         }
1832
1833         m_pvr_thread = new eDVBChannelFilePush();
1834         m_pvr_thread->enablePVRCommit(1);
1835         m_pvr_thread->setStreamMode(1);
1836         m_pvr_thread->setScatterGather(this);
1837
1838         m_event(this, evtPreStart);
1839
1840         m_pvr_thread->start(source, m_pvr_fd_dst);
1841         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1842
1843         m_state = state_ok;
1844         m_stateChanged(this);
1845
1846         return 0;
1847 }
1848
1849 void eDVBChannel::stopSource()
1850 {
1851         if (m_pvr_thread)
1852         {
1853                 m_pvr_thread->stop();
1854                 delete m_pvr_thread;
1855                 m_pvr_thread = 0;
1856         }
1857         if (m_pvr_fd_dst >= 0)
1858                 ::close(m_pvr_fd_dst);
1859         ePtr<iTsSource> d;
1860         m_tstools.setSource(d);
1861 }
1862
1863 void eDVBChannel::stopFile()
1864 {
1865         stopSource();
1866 }
1867
1868 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1869 {
1870         m_conn_cueSheetEvent = 0;
1871         m_cue = cuesheet;
1872         if (m_cue)
1873                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1874 }
1875
1876 RESULT eDVBChannel::getLength(pts_t &len)
1877 {
1878         return m_tstools.calcLen(len);
1879 }
1880
1881 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1882 {
1883         if (!decoding_demux)
1884                 return -1;
1885
1886         pts_t now;
1887
1888         int r;
1889
1890         if (mode == 0) /* demux */
1891         {
1892                 r = decoding_demux->getSTC(now, 0);
1893                 if (r)
1894                 {
1895                         eDebug("demux getSTC failed");
1896                         return -1;
1897                 }
1898         } else
1899                 now = pos; /* fixup supplied */
1900
1901         off_t off = 0; /* TODO: fixme */
1902         r = m_tstools.fixupPTS(off, now);
1903         if (r)
1904         {
1905                 eDebug("fixup PTS failed");
1906                 return -1;
1907         }
1908
1909         pos = now;
1910
1911         return 0;
1912 }
1913
1914 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1915 {
1916                         /* when seeking, we have to ensure that all buffers are flushed.
1917                            there are basically 3 buffers:
1918                            a.) the filepush's internal buffer
1919                            b.) the PVR buffer (before demux)
1920                            c.) the ratebuffer (after demux)
1921
1922                            it's important to clear them in the correct order, otherwise
1923                            the ratebuffer (for example) would immediately refill from
1924                            the not-yet-flushed PVR buffer.
1925                         */
1926
1927         m_pvr_thread->pause();
1928                 /* flush internal filepush buffer */
1929         m_pvr_thread->flush();
1930                 /* HACK: flush PVR buffer */
1931         ::ioctl(m_pvr_fd_dst, 0);
1932
1933                 /* flush ratebuffers (video, audio) */
1934         if (decoding_demux)
1935                 decoding_demux->flush();
1936
1937                 /* demux will also flush all decoder.. */
1938                 /* resume will re-query the SG */
1939         m_pvr_thread->resume();
1940 }
1941
1942 DEFINE_REF(eCueSheet);
1943
1944 eCueSheet::eCueSheet()
1945 {
1946         m_skipmode_ratio = 0;
1947 }
1948
1949 void eCueSheet::seekTo(int relative, const pts_t &pts)
1950 {
1951         m_lock.WrLock();
1952         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1953         m_lock.Unlock();
1954         m_event(evtSeek);
1955 }
1956
1957 void eCueSheet::clear()
1958 {
1959         m_lock.WrLock();
1960         m_spans.clear();
1961         m_lock.Unlock();
1962 }
1963
1964 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1965 {
1966         ASSERT(begin < end);
1967         m_lock.WrLock();
1968         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1969         m_lock.Unlock();
1970 }
1971
1972 void eCueSheet::commitSpans()
1973 {
1974         m_event(evtSpanChanged);
1975 }
1976
1977 void eCueSheet::setSkipmode(const pts_t &ratio)
1978 {
1979         m_lock.WrLock();
1980         m_skipmode_ratio = ratio;
1981         m_lock.Unlock();
1982         m_event(evtSkipmode);
1983 }
1984
1985 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1986 {
1987         m_decoding_demux = demux;
1988         m_decoder = decoder;
1989 }
1990
1991 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1992 {
1993         connection = new eConnection(this, m_event.connect(event));
1994         return 0;
1995 }