add support http ts stream.(client)
[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         x -= x % align;
1356         len += x % align;
1357
1358         if (sign)
1359                 x = -x;
1360
1361         return x;
1362 }
1363
1364         /* remember, this gets called from another thread. */
1365 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1366 {
1367         const int blocksize = 188;
1368         unsigned int max = align(10*1024*1024, blocksize);
1369         current_offset = align(current_offset, blocksize);
1370
1371         if (!m_cue)
1372         {
1373                 eDebug("no cue sheet. forcing normal play");
1374                 start = current_offset;
1375                 size = max;
1376                 return;
1377         }
1378
1379         if (m_skipmode_n)
1380         {
1381                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1382                 max = align(m_skipmode_n, blocksize);
1383         }
1384
1385         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1386         int frame_skip_success = 0;
1387
1388         if (m_skipmode_m)
1389         {
1390                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1391                 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1392                 size_t iframe_len;
1393                 off_t iframe_start = current_offset;
1394                 int frames_skipped = frames_to_skip;
1395                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1396                 {
1397                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1398                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1399                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1400                         max = align(iframe_len + 187, blocksize);
1401                         frame_skip_success = 1;
1402                 } else
1403                 {
1404                         m_skipmode_frames_remainder = 0;
1405                         eDebug("frame skipping failed, reverting to byte-skipping");
1406                 }
1407         }
1408         
1409         if (!frame_skip_success)
1410         {
1411                 current_offset += align(m_skipmode_m, blocksize);
1412                 
1413                 if (m_skipmode_m)
1414                 {
1415                         eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1416                         size_t iframe_len;
1417                         off_t iframe_start = current_offset;
1418                         
1419                         int direction = (m_skipmode_m < 0) ? -1 : +1;
1420                         if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1421                                 eDebug("failed");
1422                         else
1423                         {
1424                                 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1425                                 max = align(iframe_len, blocksize);
1426                         }
1427                 }
1428         }
1429
1430         m_cue->m_lock.RdLock();
1431
1432         while (!m_cue->m_seek_requests.empty())
1433         {
1434                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1435                 m_cue->m_lock.Unlock();
1436                 m_cue->m_lock.WrLock();
1437                 m_cue->m_seek_requests.pop_front();
1438                 m_cue->m_lock.Unlock();
1439                 m_cue->m_lock.RdLock();
1440                 int relative = seek.first;
1441                 pts_t pts = seek.second;
1442
1443                 pts_t now = 0;
1444                 if (relative)
1445                 {
1446                         if (!m_cue->m_decoder)
1447                         {
1448                                 eDebug("no decoder - can't seek relative");
1449                                 continue;
1450                         }
1451                         if (m_cue->m_decoder->getPTS(0, now))
1452                         {
1453                                 eDebug("decoder getPTS failed, can't seek relative");
1454                                 continue;
1455                         }
1456                         if (!m_cue->m_decoding_demux)
1457                         {
1458                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1459                                 start = current_offset;
1460                                 size = max;
1461                                 continue;
1462                         }
1463                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1464                         {
1465                                 eDebug("seekTo: getCurrentPosition failed!");
1466                                 continue;
1467                         }
1468                 } else if (pts < 0) /* seek relative to end */
1469                 {
1470                         pts_t len;
1471                         if (!getLength(len))
1472                         {
1473                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1474                                 pts += len;
1475                         } else
1476                         {
1477                                 eWarning("getLength failed - can't seek relative to end!");
1478                                 continue;
1479                         }
1480                 }
1481
1482                 if (relative == 1) /* pts relative */
1483                 {
1484                         pts += now;
1485                         if (pts < 0)
1486                                 pts = 0;
1487                 }
1488
1489                 if (relative != 2)
1490                         if (pts < 0)
1491                                 pts = 0;
1492
1493                 if (relative == 2) /* AP relative */
1494                 {
1495                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1496                         pts_t nextap;
1497                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1498                         {
1499                                 pts = now - 90000; /* approx. 1s */
1500                                 eDebug("AP relative seeking failed!");
1501                         } else
1502                         {
1503                                 pts = nextap;
1504                                 eDebug("next ap is %llx\n", pts);
1505                         }
1506                 }
1507
1508                 off_t offset = 0;
1509                 if (m_tstools.getOffset(offset, pts, -1))
1510                 {
1511                         eDebug("get offset for pts=%lld failed!", pts);
1512                         continue;
1513                 }
1514                 
1515                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1516                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1517         }
1518
1519         m_cue->m_lock.Unlock();
1520
1521         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1522         {
1523                 long long aligned_start = align(i->first, blocksize);
1524                 long long aligned_end = align(i->second, blocksize);
1525
1526                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1527                 {
1528                         start = current_offset;
1529                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1530                         if ((aligned_end - current_offset) > max)
1531                                 size = max;
1532                         else
1533                                 size = aligned_end - current_offset;
1534                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1535                         return;
1536                 }
1537                 if (current_offset < aligned_start)
1538                 {
1539                                 /* ok, our current offset is in an 'out' zone. */
1540                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1541                         {
1542                                         /* in normal playback, just start at the next zone. */
1543                                 start = i->first;
1544
1545                                         /* size is not 64bit! */
1546                                 if ((i->second - i->first) > max)
1547                                         size = max;
1548                                 else
1549                                         size = aligned_end - aligned_start;
1550
1551                                 eDebug("skip");
1552                                 if (m_skipmode_m < 0)
1553                                 {
1554                                         eDebug("reached SOF");
1555                                                 /* reached SOF */
1556                                         m_skipmode_m = 0;
1557                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1558                                 }
1559                         } else
1560                         {
1561                                         /* when skipping reverse, however, choose the zone before. */
1562                                 --i;
1563                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1564                                 size_t len;
1565
1566                                 aligned_start = align(i->first, blocksize);
1567                                 aligned_end = align(i->second, blocksize);
1568
1569                                 if ((aligned_end - aligned_start) > max)
1570                                         len = max;
1571                                 else
1572                                         len = aligned_end - aligned_start;
1573
1574                                 start = aligned_end - len;
1575                                 eDebug("skipping to %llx, %zd", start, len);
1576                         }
1577
1578                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1579                         return;
1580                 }
1581         }
1582
1583         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1584         {
1585                 eDebug("reached SOF");
1586                 m_skipmode_m = 0;
1587                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1588         }
1589
1590         if (m_source_span.empty())
1591         {
1592                 start = current_offset;
1593                 size = max;
1594                 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1595         } else
1596         {
1597                 start = current_offset;
1598                 size = 0;
1599         }
1600         return;
1601 }
1602
1603 void eDVBChannel::AddUse()
1604 {
1605         if (++m_use_count > 1 && m_state == state_last_instance)
1606         {
1607                 m_state = state_ok;
1608                 m_stateChanged(this);
1609         }
1610 }
1611
1612 void eDVBChannel::ReleaseUse()
1613 {
1614         if (!--m_use_count)
1615         {
1616                 m_state = state_release;
1617                 m_stateChanged(this);
1618         }
1619         else if (m_use_count == 1)
1620         {
1621                 m_state = state_last_instance;
1622                 m_stateChanged(this);
1623         }
1624 }
1625
1626 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1627 {
1628         if (m_channel_id)
1629                 m_mgr->removeChannel(this);
1630
1631         if (!channelid)
1632                 return 0;
1633
1634         m_channel_id = channelid;
1635         m_mgr->addChannel(channelid, this);
1636
1637         if (!m_frontend)
1638         {
1639                 /* no frontend, no need to tune (must be a streamed service) */
1640                 return 0;
1641         }
1642
1643         m_state = state_tuning;
1644                         /* if tuning fails, shutdown the channel immediately. */
1645         int res;
1646         res = m_frontend->get().tune(*feparm);
1647         m_current_frontend_parameters = feparm;
1648
1649         if (res)
1650         {
1651                 m_state = state_release;
1652                 m_stateChanged(this);
1653                 return res;
1654         }
1655
1656         return 0;
1657 }
1658
1659 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1660 {
1661         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1662         return 0;
1663 }
1664
1665 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1666 {
1667         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1668         return 0;
1669 }
1670
1671 RESULT eDVBChannel::getState(int &state)
1672 {
1673         state = m_state;
1674         return 0;
1675 }
1676
1677 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1678 {
1679         return -1;
1680 }
1681
1682 void eDVBChannel::SDTready(int result)
1683 {
1684         ePyObject args = PyTuple_New(2), ret;
1685         bool ok=false;
1686         if (!result)
1687         {
1688                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1689                 {
1690                         ok = true;
1691                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1692                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1693                         break;
1694                 }
1695         }
1696         if (!ok)
1697         {
1698                 PyTuple_SET_ITEM(args, 0, Py_None);
1699                 PyTuple_SET_ITEM(args, 1, Py_None);
1700                 Py_INCREF(Py_None);
1701                 Py_INCREF(Py_None);
1702         }
1703         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1704         if (ret)
1705                 Py_DECREF(ret);
1706         Py_DECREF(args);
1707         Py_DECREF(m_tsid_onid_callback);
1708         m_tsid_onid_callback = ePyObject();
1709         m_tsid_onid_demux = 0;
1710         m_SDT = 0;
1711 }
1712
1713 int eDVBChannel::reserveDemux()
1714 {
1715         ePtr<iDVBDemux> dmx;
1716         if (!getDemux(dmx, 0))
1717         {
1718                 uint8_t id;
1719                 if (!dmx->getCADemuxID(id))
1720                         return id;
1721         }
1722         return -1;
1723 }
1724
1725 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1726 {
1727         if (PyCallable_Check(callback))
1728         {
1729                 if (!getDemux(m_tsid_onid_demux, 0))
1730                 {
1731                         m_SDT = new eTable<ServiceDescriptionSection>;
1732                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1733                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1734                         {
1735                                 m_tsid_onid_demux = 0;
1736                                 m_SDT = 0;
1737                         }
1738                         else
1739                         {
1740                                 Py_INCREF(callback);
1741                                 m_tsid_onid_callback = callback;
1742                                 return 0;
1743                         }
1744                 }
1745         }
1746         return -1;
1747 }
1748
1749 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1750 {
1751         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1752
1753         if (m_frontend == NULL)
1754         {
1755                 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1756                 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1757         }
1758
1759         if (!our_demux)
1760         {
1761                 demux = 0;
1762
1763                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1764                         return -1;
1765
1766                 demux = *our_demux;
1767
1768                 /* don't hold a reference to the decoding demux, we don't need it. */
1769
1770                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1771                    the refcount is lost. thus, decoding demuxes are never allocated.
1772
1773                    this poses a big problem for PiP. */
1774
1775                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1776                         ;
1777                 else if (cap & capDecode)
1778                         our_demux = 0;
1779         }
1780         else
1781                 demux = *our_demux;
1782
1783         return 0;
1784 }
1785
1786 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1787 {
1788         frontend = 0;
1789         if (!m_frontend)
1790                 return -ENODEV;
1791         frontend = &m_frontend->get();
1792         if (frontend)
1793                 return 0;
1794         return -ENODEV;
1795 }
1796
1797 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1798 {
1799         param = m_current_frontend_parameters;
1800         return 0;
1801 }
1802
1803 RESULT eDVBChannel::playFile(const char *file)
1804 {
1805         eRawFile *f = new eRawFile();
1806         ePtr<iTsSource> source = f;
1807
1808         if (f->open(file) < 0)
1809         {
1810                 eDebug("can't open PVR file %s (%m)", file);
1811                 return -ENOENT;
1812         }
1813
1814         return playSource(source, file);
1815 }
1816
1817 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1818 {
1819         ASSERT(!m_frontend);
1820         if (m_pvr_thread)
1821         {
1822                 m_pvr_thread->stop();
1823                 delete m_pvr_thread;
1824                 m_pvr_thread = 0;
1825         }
1826
1827         if (!source->valid())
1828         {
1829                 eDebug("PVR source is not valid!");
1830                 return -ENOENT;
1831         }
1832
1833         m_tstools.setSource(source, streaminfo_file);
1834
1835                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1836                    THEN DO A REAL FIX HERE! */
1837
1838         if (m_pvr_fd_dst < 0)
1839         {
1840                 /* (this codepath needs to be improved anyway.) */
1841 #if HAVE_DVB_API_VERSION < 3
1842                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1843                 if (m_pvr_fd_dst < 0)
1844                 {
1845                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1846                         return -ENODEV;
1847                 }
1848 #else
1849                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1850                 if (demux)
1851                 {
1852                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1853                         if (m_pvr_fd_dst < 0)
1854                         {
1855                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1856                                 return -ENODEV;
1857                         }
1858                 }
1859                 else
1860                 {
1861                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1862                         return -ENODEV;
1863                 }
1864 #endif
1865         }
1866
1867         m_pvr_thread = new eDVBChannelFilePush();
1868         m_pvr_thread->enablePVRCommit(1);
1869         /* If the source specifies a length, it's a file. If not, it's a stream */
1870         m_pvr_thread->setStreamMode(source->length() <= 0);
1871         m_pvr_thread->setScatterGather(this);
1872
1873         m_event(this, evtPreStart);
1874
1875         m_pvr_thread->start(source, m_pvr_fd_dst);
1876         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1877
1878         m_state = state_ok;
1879         m_stateChanged(this);
1880
1881         return 0;
1882 }
1883
1884 void eDVBChannel::stopSource()
1885 {
1886         if (m_pvr_thread)
1887         {
1888                 m_pvr_thread->stop();
1889                 delete m_pvr_thread;
1890                 m_pvr_thread = 0;
1891         }
1892         if (m_pvr_fd_dst >= 0)
1893                 ::close(m_pvr_fd_dst);
1894         ePtr<iTsSource> d;
1895         m_tstools.setSource(d);
1896 }
1897
1898 void eDVBChannel::stopFile()
1899 {
1900         stopSource();
1901 }
1902
1903 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1904 {
1905         m_conn_cueSheetEvent = 0;
1906         m_cue = cuesheet;
1907         if (m_cue)
1908                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1909 }
1910
1911 RESULT eDVBChannel::getLength(pts_t &len)
1912 {
1913         return m_tstools.calcLen(len);
1914 }
1915
1916 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1917 {
1918         if (!decoding_demux)
1919                 return -1;
1920
1921         pts_t now;
1922
1923         int r;
1924
1925         if (mode == 0) /* demux */
1926         {
1927                 r = decoding_demux->getSTC(now, 0);
1928                 if (r)
1929                 {
1930                         eDebug("demux getSTC failed");
1931                         return -1;
1932                 }
1933         } else
1934                 now = pos; /* fixup supplied */
1935
1936         off_t off = 0; /* TODO: fixme */
1937         r = m_tstools.fixupPTS(off, now);
1938         if (r)
1939         {
1940                 eDebug("fixup PTS failed");
1941                 return -1;
1942         }
1943
1944         pos = now;
1945
1946         return 0;
1947 }
1948
1949 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1950 {
1951                         /* when seeking, we have to ensure that all buffers are flushed.
1952                            there are basically 3 buffers:
1953                            a.) the filepush's internal buffer
1954                            b.) the PVR buffer (before demux)
1955                            c.) the ratebuffer (after demux)
1956
1957                            it's important to clear them in the correct order, otherwise
1958                            the ratebuffer (for example) would immediately refill from
1959                            the not-yet-flushed PVR buffer.
1960                         */
1961
1962         m_pvr_thread->pause();
1963                 /* flush internal filepush buffer */
1964         m_pvr_thread->flush();
1965                 /* HACK: flush PVR buffer */
1966         ::ioctl(m_pvr_fd_dst, 0);
1967
1968                 /* flush ratebuffers (video, audio) */
1969         if (decoding_demux)
1970                 decoding_demux->flush();
1971
1972                 /* demux will also flush all decoder.. */
1973                 /* resume will re-query the SG */
1974         m_pvr_thread->resume();
1975 }
1976
1977 DEFINE_REF(eCueSheet);
1978
1979 eCueSheet::eCueSheet()
1980 {
1981         m_skipmode_ratio = 0;
1982 }
1983
1984 void eCueSheet::seekTo(int relative, const pts_t &pts)
1985 {
1986         m_lock.WrLock();
1987         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1988         m_lock.Unlock();
1989         m_event(evtSeek);
1990 }
1991
1992 void eCueSheet::clear()
1993 {
1994         m_lock.WrLock();
1995         m_spans.clear();
1996         m_lock.Unlock();
1997 }
1998
1999 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2000 {
2001         ASSERT(begin < end);
2002         m_lock.WrLock();
2003         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2004         m_lock.Unlock();
2005 }
2006
2007 void eCueSheet::commitSpans()
2008 {
2009         m_event(evtSpanChanged);
2010 }
2011
2012 void eCueSheet::setSkipmode(const pts_t &ratio)
2013 {
2014         m_lock.WrLock();
2015         m_skipmode_ratio = ratio;
2016         m_lock.Unlock();
2017         m_event(evtSkipmode);
2018 }
2019
2020 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2021 {
2022         m_decoding_demux = demux;
2023         m_decoder = decoder;
2024 }
2025
2026 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2027 {
2028         connection = new eConnection(this, m_event.connect(event));
2029         return 0;
2030 }