[browser] fixed menu skin to set the size automatically.
[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)
828 {
829         if (channellist)
830         {
831                 ePtr<iDVBFrontendParameters> feparm;
832                 if (!channellist->getChannelFrontendData(chid, feparm))
833                 {
834                         int system;
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, bool simulate)
855 {
856         std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
857         int ret=0;
858         if (!simulate && m_cached_channel)
859         {
860                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
861                 if(channelid==cache_chan->getChannelID())
862                         return tuner_type_channel_default(m_list, channelid);
863         }
864
865                 /* first, check if a channel is already existing. */
866 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
867         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
868         {
869 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
870                 if (i->m_channel_id == channelid)
871                 {
872 //                      eDebug("found shared channel..");
873                         return tuner_type_channel_default(m_list, channelid);
874                 }
875         }
876
877         int *decremented_cached_channel_fe_usecount=NULL,
878                 *decremented_fe_usecount=NULL;
879
880         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
881         {
882                 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
883 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
884                 if (i->m_channel_id == ignore)
885                 {
886                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
887                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
888                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
889                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
890                         // or 2 when the cached channel is not equal to the compared channel
891                         if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
892                         {
893                                 ePtr<iDVBFrontend> fe;
894                                 if (!i->m_channel->getFrontend(fe))
895                                 {
896                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
897                                         {
898                                                 if ( &(*fe) == &(*ii->m_frontend) )
899                                                 {
900                                                         --ii->m_inuse;
901                                                         decremented_fe_usecount = &ii->m_inuse;
902                                                         if (channel == &(*m_cached_channel))
903                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
904                                                         break;
905                                                 }
906                                         }
907                                 }
908                         }
909                         break;
910                 }
911         }
912
913         if (!decremented_cached_channel_fe_usecount)
914         {
915                 if (m_cached_channel)
916                 {
917                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
918                         if (channel->getUseCount() == 1)
919                         {
920                                 ePtr<iDVBFrontend> fe;
921                                 if (!channel->getFrontend(fe))
922                                 {
923                                         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
924                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
925                                         {
926                                                 if ( &(*fe) == &(*ii->m_frontend) )
927                                                 {
928                                                         --ii->m_inuse;
929                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
930                                                         break;
931                                                 }
932                                         }
933                                 }
934                         }
935                 }
936         }
937         else
938                 decremented_cached_channel_fe_usecount=NULL;
939
940         ePtr<iDVBFrontendParameters> feparm;
941
942         if (!m_list)
943         {
944                 eDebug("no channel list set!");
945                 goto error;
946         }
947
948         if (m_list->getChannelFrontendData(channelid, feparm))
949         {
950                 eDebug("channel not found!");
951                 goto error;
952         }
953
954         ret = canAllocateFrontend(feparm, simulate);
955
956 error:
957         if (decremented_fe_usecount)
958                 ++(*decremented_fe_usecount);
959         if (decremented_cached_channel_fe_usecount)
960                 ++(*decremented_cached_channel_fe_usecount);
961
962         return ret;
963 }
964
965 bool eDVBResourceManager::canMeasureFrontendInputPower()
966 {
967         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
968         {
969                 return i->m_frontend->readInputpower() >= 0;
970         }
971         return false;
972 }
973
974 class eDVBChannelFilePush: public eFilePushThread
975 {
976 public:
977         eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
978         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
979
980                         /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
981                         /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
982         void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
983 protected:
984         int m_iframe_search, m_iframe_state, m_pid;
985         int m_timebase_change;
986         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
987 };
988
989 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
990 {
991 #if 0
992         if (m_timebase_change)
993         {
994                 eDebug("timebase change: %d", m_timebase_change);
995                 int offset;
996                 for (offset = 0; offset < len; offset += 188)
997                 {
998                         unsigned char *pkt = (unsigned char*)_data + offset;
999                         if (pkt[1] & 0x40) /* pusi */
1000                         {
1001                                 if (pkt[3] & 0x20) // adaption field present?
1002                                         pkt += pkt[4] + 4 + 1;  /* skip adaption field and header */
1003                                 else
1004                                         pkt += 4; /* skip header */
1005                                 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1006                                 {
1007                                         eWarning("broken startcode");
1008                                         continue;
1009                                 }
1010
1011                                 pts_t pts = 0;
1012
1013                                 if (pkt[7] & 0x80) // PTS present?
1014                                 {
1015                                         pts  = ((unsigned long long)(pkt[ 9]&0xE))  << 29;
1016                                         pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1017                                         pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1018                                         pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1019                                         pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1020
1021 #if 0
1022                                         off_t off = 0;
1023                                         RESULT r = m_tstools.fixupPTS(off, pts);
1024                                         if (r)
1025                                                 eWarning("fixup PTS while trickmode playback failed.\n");
1026 #endif
1027
1028                                         int sec = pts / 90000;
1029                                         int frm = pts % 90000;
1030                                         int min = sec / 60;
1031                                         sec %= 60;
1032                                         int hr = min / 60;
1033                                         min %= 60;
1034                                         int d = hr / 24;
1035                                         hr %= 24;
1036
1037 //                                      eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1038
1039                                         pts += 0x80000000LL;
1040                                         pts *= m_timebase_change;
1041                                         pts >>= 16;
1042
1043                                         sec = pts / 90000;
1044                                         frm = pts % 90000;
1045                                         min = sec / 60;
1046                                         sec %= 60;
1047                                         hr = min / 60;
1048                                         min %= 60;
1049                                         d = hr / 24;
1050                                         hr %= 24;
1051
1052 //                                      eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1053
1054                                         pkt[9] &= ~0xE;
1055                                         pkt[10] = 0;
1056                                         pkt[11] &= ~1;
1057                                         pkt[12] = 0;
1058                                         pkt[13] &= ~1;
1059
1060                                         pkt[9]  |= (pts >> 29) & 0xE;
1061                                         pkt[10] |= (pts >> 22) & 0xFF;
1062                                         pkt[11] |= (pts >> 14) & 0xFE;
1063                                         pkt[12] |= (pts >> 7) & 0xFF;
1064                                         pkt[13] |= (pts << 1) & 0xFE;
1065                                 }
1066                         }
1067                 }
1068         }
1069 #endif
1070
1071 #if 0
1072         if (!m_iframe_search)
1073                 return len;
1074
1075         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1076
1077 //      eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1078
1079         unsigned char *d = data;
1080         while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1081         {
1082                 int offset = d - data;
1083                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1084                 unsigned char *ts = data + ts_offset;
1085                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1086
1087                 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
1088                 {
1089                         int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1090                         d += 4;
1091
1092 //                      eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1093
1094                         if (m_iframe_state == 1)
1095                         {
1096                                         /* we are allowing data, and stop allowing data on the next frame.
1097                                            we now found a frame. so stop here. */
1098                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1099                                 current_span_remaining = 0;
1100                                 m_iframe_state = 0;
1101                                 unsigned char *fts = ts + 188;
1102                                 while (fts < (data + len))
1103                                 {
1104                                         fts[1] |= 0x1f;
1105                                         fts[2] |= 0xff; /* drop packet */
1106                                         fts += 188;
1107                                 }
1108
1109                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1110                         } else
1111                         {
1112                                 if (picture_type != 1) /* we are only interested in I frames */
1113                                         continue;
1114
1115                                 unsigned char *fts = data;
1116                                 while (fts < ts)
1117                                 {
1118                                         fts[1] |= 0x1f;
1119                                         fts[2] |= 0xff; /* drop packet */
1120
1121                                         fts += 188;
1122                                 }
1123
1124                                 m_iframe_state = 1;
1125                         }
1126                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1127                 {
1128                                 /* verify that this is actually a PES header, not just some ES data */
1129                         if (ts[1] & 0x40) /* PUSI set */
1130                         {
1131                                 int payload_start = 4;
1132                                 if (ts[3] & 0x20) /* adaptation field present */
1133                                         payload_start += ts[4] + 1; /* skip AF */
1134                                 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1135                                 {
1136                                         if (m_pid != pid)
1137                                         {
1138                                                 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1139                                                 m_pid = pid;
1140                                         }
1141                                 }
1142                         }
1143 //                      m_pid = 0x6e;
1144                         d += 4;
1145                 } else
1146                         d += 4; /* ignore */
1147         }
1148
1149         if (m_iframe_state == 1)
1150                 return len;
1151         else
1152                 return 0; /* we need find an iframe first */
1153 #else
1154         return len;
1155 #endif
1156 }
1157
1158 DEFINE_REF(eDVBChannel);
1159
1160 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1161 {
1162         m_frontend = frontend;
1163
1164         m_pvr_thread = 0;
1165         m_pvr_fd_dst = -1;
1166
1167         m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1168
1169         if (m_frontend)
1170                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1171 }
1172
1173 eDVBChannel::~eDVBChannel()
1174 {
1175         if (m_channel_id)
1176                 m_mgr->removeChannel(this);
1177
1178         stopFile();
1179 }
1180
1181 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1182 {
1183         int state, ourstate = 0;
1184
1185                 /* if we are already in shutdown, don't change state. */
1186         if (m_state == state_release)
1187                 return;
1188
1189         if (fe->getState(state))
1190                 return;
1191
1192         if (state == iDVBFrontend::stateLock)
1193         {
1194                 eDebug("OURSTATE: ok");
1195                 ourstate = state_ok;
1196         } else if (state == iDVBFrontend::stateTuning)
1197         {
1198                 eDebug("OURSTATE: tuning");
1199                 ourstate = state_tuning;
1200         } else if (state == iDVBFrontend::stateLostLock)
1201         {
1202                         /* on managed channels, we try to retune in order to re-acquire lock. */
1203                 if (m_current_frontend_parameters)
1204                 {
1205                         eDebug("OURSTATE: lost lock, trying to retune");
1206                         ourstate = state_tuning;
1207                         m_frontend->get().tune(*m_current_frontend_parameters);
1208                 } else
1209                         /* on unmanaged channels, we don't do this. the client will do this. */
1210                 {
1211                         eDebug("OURSTATE: lost lock, unavailable now.");
1212                         ourstate = state_unavailable;
1213                 }
1214         } else if (state == iDVBFrontend::stateFailed)
1215         {
1216 #ifdef BUILD_VUPLUS /* ikseong  */
1217                 if (m_current_frontend_parameters)
1218                 {
1219                         eDebug("OURSTATE: lost lock, trying to retune");
1220                         ourstate = state_tuning;
1221                         m_frontend->get().tune(*m_current_frontend_parameters);
1222                 } 
1223                 else
1224                 {
1225                         eDebug("OURSTATE: failed");
1226                         ourstate = state_failed;
1227                 }
1228 #else
1229                 eDebug("OURSTATE: failed");
1230                 ourstate = state_failed;
1231 #endif          
1232         } else
1233                 eFatal("state unknown");
1234
1235         if (ourstate != m_state)
1236         {
1237                 m_state = ourstate;
1238                 m_stateChanged(this);
1239         }
1240 }
1241
1242 void eDVBChannel::pvrEvent(int event)
1243 {
1244         switch (event)
1245         {
1246         case eFilePushThread::evtEOF:
1247                 eDebug("eDVBChannel: End of file!");
1248                 m_event(this, evtEOF);
1249                 break;
1250         case eFilePushThread::evtUser: /* start */
1251                 eDebug("SOF");
1252                 m_event(this, evtSOF);
1253                 break;
1254         }
1255 }
1256
1257 void eDVBChannel::cueSheetEvent(int event)
1258 {
1259                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1260         if (!m_pvr_thread)
1261                 return;
1262         switch (event)
1263         {
1264         case eCueSheet::evtSeek:
1265                 eDebug("seek.");
1266                 flushPVR(m_cue->m_decoding_demux);
1267                 break;
1268         case eCueSheet::evtSkipmode:
1269         {
1270                 {
1271                         m_cue->m_lock.WrLock();
1272                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1273                         m_cue->m_lock.Unlock();
1274                         eRdLocker l(m_cue->m_lock);
1275                         if (m_cue->m_skipmode_ratio)
1276                         {
1277                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1278                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1279                                                 /* i agree that this might look a bit like black magic. */
1280                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1281                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1282                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1283                                 m_skipmode_frames_remainder = 0;
1284
1285                                 if (m_cue->m_skipmode_ratio < 0)
1286                                         m_skipmode_m -= m_skipmode_n;
1287
1288                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1289
1290                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1291                                 {
1292                                         eWarning("something is wrong with this calculation");
1293                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1294                                 }
1295                         } else
1296                         {
1297                                 eDebug("skipmode ratio is 0, normal play");
1298                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1299                         }
1300                 }
1301                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1302                 if (m_cue->m_skipmode_ratio != 0)
1303                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1304                 else
1305                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1306                 eDebug("flush pvr");
1307                 flushPVR(m_cue->m_decoding_demux);
1308                 eDebug("done");
1309                 break;
1310         }
1311         case eCueSheet::evtSpanChanged:
1312         {
1313                 m_source_span.clear();
1314                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1315                 {
1316                         off_t offset_in, offset_out;
1317                         pts_t pts_in = i->first, pts_out = i->second;
1318                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1319                         {
1320                                 eDebug("span translation failed.\n");
1321                                 continue;
1322                         }
1323                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1324                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1325                 }
1326                 break;
1327         }
1328         }
1329 }
1330
1331         /* align toward zero */
1332 static inline long long align(long long x, int align)
1333 {
1334         int sign = x < 0;
1335
1336         if (sign)
1337                 x = -x;
1338
1339         x -= x % align;
1340
1341         if (sign)
1342                 x = -x;
1343
1344         return x;
1345 }
1346
1347         /* align toward zero */
1348 static inline long long align_with_len(long long x, int align, size_t &len)
1349 {
1350         int sign = x < 0;
1351
1352         if (sign)
1353                 x = -x;
1354
1355         int r = x % align;
1356         x -= r;
1357         len += r;
1358
1359         if (sign)
1360                 x = -x;
1361
1362         return x;
1363 }
1364
1365         /* remember, this gets called from another thread. */
1366 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1367 {
1368         const int blocksize = 188;
1369         unsigned int max = align(10*1024*1024, blocksize);
1370         current_offset = align(current_offset, blocksize);
1371
1372         if (!m_cue)
1373         {
1374                 eDebug("no cue sheet. forcing normal play");
1375                 start = current_offset;
1376                 size = max;
1377                 return;
1378         }
1379
1380         if (m_skipmode_n)
1381         {
1382                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1383                 max = align(m_skipmode_n, blocksize);
1384         }
1385
1386         eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1387         int frame_skip_success = 0;
1388
1389         if (m_skipmode_m)
1390         {
1391                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1392                 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1393                 size_t iframe_len;
1394                 off_t iframe_start = current_offset;
1395                 int frames_skipped = frames_to_skip;
1396                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1397                 {
1398                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1399                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1400                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1401                         max = align(iframe_len + 187, blocksize);
1402                         frame_skip_success = 1;
1403                 } else
1404                 {
1405                         m_skipmode_frames_remainder = 0;
1406                         eDebug("frame skipping failed, reverting to byte-skipping");
1407                 }
1408         }
1409         
1410         if (!frame_skip_success)
1411         {
1412                 current_offset += align(m_skipmode_m, blocksize);
1413                 if(current_offset < 0)
1414                         current_offset = 0;
1415                 else
1416                 {
1417                         if (m_skipmode_m)
1418                         {
1419                                 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1420                                 size_t iframe_len;
1421                                 off_t start_offset = current_offset;
1422                                 off_t new_offset = start_offset;
1423                                 int direction = (m_skipmode_m < 0) ? -1 : +1;
1424                                 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1425                                         eDebug("failed");
1426                                 else
1427                                 {
1428                                         current_offset = align_with_len(new_offset, blocksize, iframe_len);
1429                                         max = align(iframe_len, blocksize);
1430                                 }
1431                         }
1432                 }
1433         }
1434
1435         m_cue->m_lock.RdLock();
1436
1437         while (!m_cue->m_seek_requests.empty())
1438         {
1439                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1440                 m_cue->m_lock.Unlock();
1441                 m_cue->m_lock.WrLock();
1442                 m_cue->m_seek_requests.pop_front();
1443                 m_cue->m_lock.Unlock();
1444                 m_cue->m_lock.RdLock();
1445                 int relative = seek.first;
1446                 pts_t pts = seek.second;
1447
1448                 pts_t now = 0;
1449                 if (relative)
1450                 {
1451                         if (!m_cue->m_decoder)
1452                         {
1453                                 eDebug("no decoder - can't seek relative");
1454                                 continue;
1455                         }
1456                         if (m_cue->m_decoder->getPTS(0, now))
1457                         {
1458                                 eDebug("decoder getPTS failed, can't seek relative");
1459                                 continue;
1460                         }
1461                         if (!m_cue->m_decoding_demux)
1462                         {
1463                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1464                                 start = current_offset;
1465                                 size = max;
1466                                 continue;
1467                         }
1468                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1469                         {
1470                                 eDebug("seekTo: getCurrentPosition failed!");
1471                                 continue;
1472                         }
1473                 } else if (pts < 0) /* seek relative to end */
1474                 {
1475                         pts_t len;
1476                         if (!getLength(len))
1477                         {
1478                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1479                                 pts += len;
1480                         } else
1481                         {
1482                                 eWarning("getLength failed - can't seek relative to end!");
1483                                 continue;
1484                         }
1485                 }
1486
1487                 if (relative == 1) /* pts relative */
1488                 {
1489                         pts += now;
1490                         if (pts < 0)
1491                                 pts = 0;
1492                 }
1493
1494                 if (relative != 2)
1495                         if (pts < 0)
1496                                 pts = 0;
1497
1498                 if (relative == 2) /* AP relative */
1499                 {
1500                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1501                         pts_t nextap;
1502                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1503                         {
1504                                 pts = now - 90000; /* approx. 1s */
1505                                 eDebug("AP relative seeking failed!");
1506                         } else
1507                         {
1508                                 pts = nextap;
1509                                 eDebug("next ap is %llx\n", pts);
1510                         }
1511                 }
1512
1513                 off_t offset = 0;
1514                 if (m_tstools.getOffset(offset, pts, -1))
1515                 {
1516                         eDebug("get offset for pts=%lld failed!", pts);
1517                         continue;
1518                 }
1519                 
1520                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1521                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1522         }
1523
1524         m_cue->m_lock.Unlock();
1525
1526         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1527         {
1528                 long long aligned_start = align(i->first, blocksize);
1529                 long long aligned_end = align(i->second, blocksize);
1530
1531                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1532                 {
1533                         start = current_offset;
1534                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1535                         if ((aligned_end - current_offset) > max)
1536                                 size = max;
1537                         else
1538                                 size = aligned_end - current_offset;
1539                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1540                         return;
1541                 }
1542                 if (current_offset < aligned_start)
1543                 {
1544                                 /* ok, our current offset is in an 'out' zone. */
1545                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1546                         {
1547                                         /* in normal playback, just start at the next zone. */
1548                                 start = i->first;
1549
1550                                         /* size is not 64bit! */
1551                                 if ((i->second - i->first) > max)
1552                                         size = max;
1553                                 else
1554                                         size = aligned_end - aligned_start;
1555
1556                                 eDebug("skip");
1557                                 if (m_skipmode_m < 0)
1558                                 {
1559                                         eDebug("reached SOF");
1560                                                 /* reached SOF */
1561                                         m_skipmode_m = 0;
1562                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1563                                 }
1564                         } else
1565                         {
1566                                         /* when skipping reverse, however, choose the zone before. */
1567                                 --i;
1568                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1569                                 size_t len;
1570
1571                                 aligned_start = align(i->first, blocksize);
1572                                 aligned_end = align(i->second, blocksize);
1573
1574                                 if ((aligned_end - aligned_start) > max)
1575                                         len = max;
1576                                 else
1577                                         len = aligned_end - aligned_start;
1578
1579                                 start = aligned_end - len;
1580                                 eDebug("skipping to %llx, %zd", start, len);
1581                         }
1582
1583                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1584                         return;
1585                 }
1586         }
1587
1588         if(current_offset <0)
1589                 current_offset =0;
1590         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1591         {
1592                 eDebug("reached SOF");
1593                 m_skipmode_m = 0;
1594                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1595         }
1596         if (m_source_span.empty())
1597         {
1598                 start = current_offset;
1599                 size = max;
1600                 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1601         } else
1602         {
1603                 start = current_offset;
1604                 size = 0;
1605         }
1606         return;
1607 }
1608
1609 void eDVBChannel::AddUse()
1610 {
1611         if (++m_use_count > 1 && m_state == state_last_instance)
1612         {
1613                 m_state = state_ok;
1614                 m_stateChanged(this);
1615         }
1616 }
1617
1618 void eDVBChannel::ReleaseUse()
1619 {
1620         if (!--m_use_count)
1621         {
1622                 m_state = state_release;
1623                 m_stateChanged(this);
1624         }
1625         else if (m_use_count == 1)
1626         {
1627                 m_state = state_last_instance;
1628                 m_stateChanged(this);
1629         }
1630 }
1631
1632 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1633 {
1634         if (m_channel_id)
1635                 m_mgr->removeChannel(this);
1636
1637         if (!channelid)
1638                 return 0;
1639
1640         m_channel_id = channelid;
1641         m_mgr->addChannel(channelid, this);
1642
1643         if (!m_frontend)
1644         {
1645                 /* no frontend, no need to tune (must be a streamed service) */
1646                 return 0;
1647         }
1648
1649         m_state = state_tuning;
1650                         /* if tuning fails, shutdown the channel immediately. */
1651         int res;
1652         res = m_frontend->get().tune(*feparm);
1653         m_current_frontend_parameters = feparm;
1654
1655         if (res)
1656         {
1657                 m_state = state_release;
1658                 m_stateChanged(this);
1659                 return res;
1660         }
1661
1662         return 0;
1663 }
1664
1665 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1666 {
1667         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1668         return 0;
1669 }
1670
1671 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1672 {
1673         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1674         return 0;
1675 }
1676
1677 RESULT eDVBChannel::getState(int &state)
1678 {
1679         state = m_state;
1680         return 0;
1681 }
1682
1683 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1684 {
1685         return -1;
1686 }
1687
1688 void eDVBChannel::SDTready(int result)
1689 {
1690         ePyObject args = PyTuple_New(2), ret;
1691         bool ok=false;
1692         if (!result)
1693         {
1694                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1695                 {
1696                         ok = true;
1697                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1698                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1699                         break;
1700                 }
1701         }
1702         if (!ok)
1703         {
1704                 PyTuple_SET_ITEM(args, 0, Py_None);
1705                 PyTuple_SET_ITEM(args, 1, Py_None);
1706                 Py_INCREF(Py_None);
1707                 Py_INCREF(Py_None);
1708         }
1709         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1710         if (ret)
1711                 Py_DECREF(ret);
1712         Py_DECREF(args);
1713         Py_DECREF(m_tsid_onid_callback);
1714         m_tsid_onid_callback = ePyObject();
1715         m_tsid_onid_demux = 0;
1716         m_SDT = 0;
1717 }
1718
1719 int eDVBChannel::reserveDemux()
1720 {
1721         ePtr<iDVBDemux> dmx;
1722         if (!getDemux(dmx, 0))
1723         {
1724                 uint8_t id;
1725                 if (!dmx->getCADemuxID(id))
1726                         return id;
1727         }
1728         return -1;
1729 }
1730
1731 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1732 {
1733         if (PyCallable_Check(callback))
1734         {
1735                 if (!getDemux(m_tsid_onid_demux, 0))
1736                 {
1737                         m_SDT = new eTable<ServiceDescriptionSection>;
1738                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1739                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1740                         {
1741                                 m_tsid_onid_demux = 0;
1742                                 m_SDT = 0;
1743                         }
1744                         else
1745                         {
1746                                 Py_INCREF(callback);
1747                                 m_tsid_onid_callback = callback;
1748                                 return 0;
1749                         }
1750                 }
1751         }
1752         return -1;
1753 }
1754
1755 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1756 {
1757         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1758
1759         if (m_frontend == NULL)
1760         {
1761                 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1762                 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1763         }
1764
1765         if (!our_demux)
1766         {
1767                 demux = 0;
1768
1769                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1770                         return -1;
1771
1772                 demux = *our_demux;
1773
1774                 /* don't hold a reference to the decoding demux, we don't need it. */
1775
1776                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1777                    the refcount is lost. thus, decoding demuxes are never allocated.
1778
1779                    this poses a big problem for PiP. */
1780
1781                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1782                         ;
1783                 else if (cap & capDecode)
1784                         our_demux = 0;
1785         }
1786         else
1787                 demux = *our_demux;
1788
1789         return 0;
1790 }
1791
1792 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1793 {
1794         frontend = 0;
1795         if (!m_frontend)
1796                 return -ENODEV;
1797         frontend = &m_frontend->get();
1798         if (frontend)
1799                 return 0;
1800         return -ENODEV;
1801 }
1802
1803 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1804 {
1805         param = m_current_frontend_parameters;
1806         return 0;
1807 }
1808
1809 RESULT eDVBChannel::playFile(const char *file)
1810 {
1811         eRawFile *f = new eRawFile();
1812         ePtr<iTsSource> source = f;
1813
1814         if (f->open(file) < 0)
1815         {
1816                 eDebug("can't open PVR file %s (%m)", file);
1817                 return -ENOENT;
1818         }
1819
1820         return playSource(source, file);
1821 }
1822
1823 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1824 {
1825         ASSERT(!m_frontend);
1826         if (m_pvr_thread)
1827         {
1828                 m_pvr_thread->stop();
1829                 delete m_pvr_thread;
1830                 m_pvr_thread = 0;
1831         }
1832
1833         if (!source->valid())
1834         {
1835                 eDebug("PVR source is not valid!");
1836                 return -ENOENT;
1837         }
1838
1839         m_tstools.setSource(source, streaminfo_file);
1840
1841                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1842                    THEN DO A REAL FIX HERE! */
1843
1844         if (m_pvr_fd_dst < 0)
1845         {
1846                 /* (this codepath needs to be improved anyway.) */
1847 #if HAVE_DVB_API_VERSION < 3
1848                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1849                 if (m_pvr_fd_dst < 0)
1850                 {
1851                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1852                         return -ENODEV;
1853                 }
1854 #else
1855                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1856                 if (demux)
1857                 {
1858                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1859                         if (m_pvr_fd_dst < 0)
1860                         {
1861                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1862                                 return -ENODEV;
1863                         }
1864                 }
1865                 else
1866                 {
1867                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1868                         return -ENODEV;
1869                 }
1870 #endif
1871         }
1872
1873         m_pvr_thread = new eDVBChannelFilePush();
1874         m_pvr_thread->enablePVRCommit(1);
1875         /* If the source specifies a length, it's a file. If not, it's a stream */
1876         m_pvr_thread->setStreamMode(source->length() <= 0);
1877         m_pvr_thread->setScatterGather(this);
1878
1879         m_event(this, evtPreStart);
1880
1881         m_pvr_thread->start(source, m_pvr_fd_dst);
1882         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1883
1884         m_state = state_ok;
1885         m_stateChanged(this);
1886
1887         return 0;
1888 }
1889
1890 void eDVBChannel::stopSource()
1891 {
1892         if (m_pvr_thread)
1893         {
1894                 m_pvr_thread->stop();
1895                 delete m_pvr_thread;
1896                 m_pvr_thread = 0;
1897         }
1898         if (m_pvr_fd_dst >= 0)
1899                 ::close(m_pvr_fd_dst);
1900         ePtr<iTsSource> d;
1901         m_tstools.setSource(d);
1902 }
1903
1904 void eDVBChannel::stopFile()
1905 {
1906         stopSource();
1907 }
1908
1909 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1910 {
1911         m_conn_cueSheetEvent = 0;
1912         m_cue = cuesheet;
1913         if (m_cue)
1914                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1915 }
1916
1917 RESULT eDVBChannel::getLength(pts_t &len)
1918 {
1919         return m_tstools.calcLen(len);
1920 }
1921
1922 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1923 {
1924         if (!decoding_demux)
1925                 return -1;
1926
1927         pts_t now;
1928
1929         int r;
1930
1931         if (mode == 0) /* demux */
1932         {
1933                 r = decoding_demux->getSTC(now, 0);
1934                 if (r)
1935                 {
1936                         eDebug("demux getSTC failed");
1937                         return -1;
1938                 }
1939         } else
1940                 now = pos; /* fixup supplied */
1941
1942         off_t off = 0; /* TODO: fixme */
1943         r = m_tstools.fixupPTS(off, now);
1944         if (r)
1945         {
1946                 eDebug("fixup PTS failed");
1947                 return -1;
1948         }
1949
1950         pos = now;
1951
1952         return 0;
1953 }
1954
1955 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1956 {
1957                         /* when seeking, we have to ensure that all buffers are flushed.
1958                            there are basically 3 buffers:
1959                            a.) the filepush's internal buffer
1960                            b.) the PVR buffer (before demux)
1961                            c.) the ratebuffer (after demux)
1962
1963                            it's important to clear them in the correct order, otherwise
1964                            the ratebuffer (for example) would immediately refill from
1965                            the not-yet-flushed PVR buffer.
1966                         */
1967
1968         m_pvr_thread->pause();
1969                 /* flush internal filepush buffer */
1970         m_pvr_thread->flush();
1971                 /* HACK: flush PVR buffer */
1972         ::ioctl(m_pvr_fd_dst, 0);
1973
1974                 /* flush ratebuffers (video, audio) */
1975         if (decoding_demux)
1976                 decoding_demux->flush();
1977
1978                 /* demux will also flush all decoder.. */
1979                 /* resume will re-query the SG */
1980         m_pvr_thread->resume();
1981 }
1982
1983 DEFINE_REF(eCueSheet);
1984
1985 eCueSheet::eCueSheet()
1986 {
1987         m_skipmode_ratio = 0;
1988 }
1989
1990 void eCueSheet::seekTo(int relative, const pts_t &pts)
1991 {
1992         m_lock.WrLock();
1993         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1994         m_lock.Unlock();
1995         m_event(evtSeek);
1996 }
1997
1998 void eCueSheet::clear()
1999 {
2000         m_lock.WrLock();
2001         m_spans.clear();
2002         m_lock.Unlock();
2003 }
2004
2005 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2006 {
2007         ASSERT(begin < end);
2008         m_lock.WrLock();
2009         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2010         m_lock.Unlock();
2011 }
2012
2013 void eCueSheet::commitSpans()
2014 {
2015         m_event(evtSpanChanged);
2016 }
2017
2018 void eCueSheet::setSkipmode(const pts_t &ratio)
2019 {
2020         m_lock.WrLock();
2021         m_skipmode_ratio = ratio;
2022         m_lock.Unlock();
2023         m_event(evtSkipmode);
2024 }
2025
2026 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2027 {
2028         m_decoding_demux = demux;
2029         m_decoder = decoder;
2030 }
2031
2032 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2033 {
2034         connection = new eConnection(this, m_event.connect(event));
2035         return 0;
2036 }