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