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