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