Merge remote branch 'origin/pootle-import' into 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                 eDebug("OURSTATE: failed");
1191                 ourstate = state_failed;
1192         } else
1193                 eFatal("state unknown");
1194
1195         if (ourstate != m_state)
1196         {
1197                 m_state = ourstate;
1198                 m_stateChanged(this);
1199         }
1200 }
1201
1202 void eDVBChannel::pvrEvent(int event)
1203 {
1204         switch (event)
1205         {
1206         case eFilePushThread::evtEOF:
1207                 eDebug("eDVBChannel: End of file!");
1208                 m_event(this, evtEOF);
1209                 break;
1210         case eFilePushThread::evtUser: /* start */
1211                 eDebug("SOF");
1212                 m_event(this, evtSOF);
1213                 break;
1214         }
1215 }
1216
1217 void eDVBChannel::cueSheetEvent(int event)
1218 {
1219                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1220         if (!m_pvr_thread)
1221                 return;
1222         switch (event)
1223         {
1224         case eCueSheet::evtSeek:
1225                 eDebug("seek.");
1226                 flushPVR(m_cue->m_decoding_demux);
1227                 break;
1228         case eCueSheet::evtSkipmode:
1229         {
1230                 {
1231                         m_cue->m_lock.WrLock();
1232                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1233                         m_cue->m_lock.Unlock();
1234                         eRdLocker l(m_cue->m_lock);
1235                         if (m_cue->m_skipmode_ratio)
1236                         {
1237                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1238                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1239                                                 /* i agree that this might look a bit like black magic. */
1240                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1241                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1242                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1243                                 m_skipmode_frames_remainder = 0;
1244
1245                                 if (m_cue->m_skipmode_ratio < 0)
1246                                         m_skipmode_m -= m_skipmode_n;
1247
1248                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1249
1250                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1251                                 {
1252                                         eWarning("something is wrong with this calculation");
1253                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1254                                 }
1255                         } else
1256                         {
1257                                 eDebug("skipmode ratio is 0, normal play");
1258                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1259                         }
1260                 }
1261                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1262                 if (m_cue->m_skipmode_ratio != 0)
1263                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1264                 else
1265                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1266                 eDebug("flush pvr");
1267                 flushPVR(m_cue->m_decoding_demux);
1268                 eDebug("done");
1269                 break;
1270         }
1271         case eCueSheet::evtSpanChanged:
1272         {
1273                 m_source_span.clear();
1274                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1275                 {
1276                         off_t offset_in, offset_out;
1277                         pts_t pts_in = i->first, pts_out = i->second;
1278                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1279                         {
1280                                 eDebug("span translation failed.\n");
1281                                 continue;
1282                         }
1283                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1284                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1285                 }
1286                 break;
1287         }
1288         }
1289 }
1290
1291         /* align toward zero */
1292 static inline long long align(long long x, int align)
1293 {
1294         int sign = x < 0;
1295
1296         if (sign)
1297                 x = -x;
1298
1299         x -= x % align;
1300
1301         if (sign)
1302                 x = -x;
1303
1304         return x;
1305 }
1306
1307         /* align toward zero */
1308 static inline long long align_with_len(long long x, int align, size_t &len)
1309 {
1310         int sign = x < 0;
1311
1312         if (sign)
1313                 x = -x;
1314
1315         x -= x % align;
1316         len += x % align;
1317
1318         if (sign)
1319                 x = -x;
1320
1321         return x;
1322 }
1323
1324         /* remember, this gets called from another thread. */
1325 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1326 {
1327         const int blocksize = 188;
1328         unsigned int max = align(10*1024*1024, blocksize);
1329         current_offset = align(current_offset, blocksize);
1330
1331         if (!m_cue)
1332         {
1333                 eDebug("no cue sheet. forcing normal play");
1334                 start = current_offset;
1335                 size = max;
1336                 return;
1337         }
1338
1339         if (m_skipmode_n)
1340         {
1341                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1342                 max = align(m_skipmode_n, blocksize);
1343         }
1344
1345         eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1346         int frame_skip_success = 0;
1347
1348         if (m_skipmode_m)
1349         {
1350                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1351                 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1352                 size_t iframe_len;
1353                 off_t iframe_start = current_offset;
1354                 int frames_skipped = frames_to_skip;
1355                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1356                 {
1357                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1358                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1359                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1360                         max = align(iframe_len + 187, blocksize);
1361                         frame_skip_success = 1;
1362                 } else
1363                 {
1364                         m_skipmode_frames_remainder = 0;
1365                         eDebug("frame skipping failed, reverting to byte-skipping");
1366                 }
1367         }
1368         
1369         if (!frame_skip_success)
1370         {
1371                 current_offset += align(m_skipmode_m, blocksize);
1372                 
1373                 if (m_skipmode_m)
1374                 {
1375                         eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1376                         size_t iframe_len;
1377                         off_t iframe_start = current_offset;
1378                         
1379                         int direction = (m_skipmode_m < 0) ? -1 : +1;
1380                         if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1381                                 eDebug("failed");
1382                         else
1383                         {
1384                                 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1385                                 max = align(iframe_len, blocksize);
1386                         }
1387                 }
1388         }
1389
1390         m_cue->m_lock.RdLock();
1391
1392         while (!m_cue->m_seek_requests.empty())
1393         {
1394                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1395                 m_cue->m_lock.Unlock();
1396                 m_cue->m_lock.WrLock();
1397                 m_cue->m_seek_requests.pop_front();
1398                 m_cue->m_lock.Unlock();
1399                 m_cue->m_lock.RdLock();
1400                 int relative = seek.first;
1401                 pts_t pts = seek.second;
1402
1403                 pts_t now = 0;
1404                 if (relative)
1405                 {
1406                         if (!m_cue->m_decoder)
1407                         {
1408                                 eDebug("no decoder - can't seek relative");
1409                                 continue;
1410                         }
1411                         if (m_cue->m_decoder->getPTS(0, now))
1412                         {
1413                                 eDebug("decoder getPTS failed, can't seek relative");
1414                                 continue;
1415                         }
1416                         if (!m_cue->m_decoding_demux)
1417                         {
1418                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1419                                 start = current_offset;
1420                                 size = max;
1421                                 continue;
1422                         }
1423                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1424                         {
1425                                 eDebug("seekTo: getCurrentPosition failed!");
1426                                 continue;
1427                         }
1428                 } else if (pts < 0) /* seek relative to end */
1429                 {
1430                         pts_t len;
1431                         if (!getLength(len))
1432                         {
1433                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1434                                 pts += len;
1435                         } else
1436                         {
1437                                 eWarning("getLength failed - can't seek relative to end!");
1438                                 continue;
1439                         }
1440                 }
1441
1442                 if (relative == 1) /* pts relative */
1443                 {
1444                         pts += now;
1445                         if (pts < 0)
1446                                 pts = 0;
1447                 }
1448
1449                 if (relative != 2)
1450                         if (pts < 0)
1451                                 pts = 0;
1452
1453                 if (relative == 2) /* AP relative */
1454                 {
1455                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1456                         pts_t nextap;
1457                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1458                         {
1459                                 pts = now - 90000; /* approx. 1s */
1460                                 eDebug("AP relative seeking failed!");
1461                         } else
1462                         {
1463                                 pts = nextap;
1464                                 eDebug("next ap is %llx\n", pts);
1465                         }
1466                 }
1467
1468                 off_t offset = 0;
1469                 if (m_tstools.getOffset(offset, pts, -1))
1470                 {
1471                         eDebug("get offset for pts=%lld failed!", pts);
1472                         continue;
1473                 }
1474                 
1475                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1476                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1477         }
1478
1479         m_cue->m_lock.Unlock();
1480
1481         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1482         {
1483                 long long aligned_start = align(i->first, blocksize);
1484                 long long aligned_end = align(i->second, blocksize);
1485
1486                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1487                 {
1488                         start = current_offset;
1489                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1490                         if ((aligned_end - current_offset) > max)
1491                                 size = max;
1492                         else
1493                                 size = aligned_end - current_offset;
1494                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1495                         return;
1496                 }
1497                 if (current_offset < aligned_start)
1498                 {
1499                                 /* ok, our current offset is in an 'out' zone. */
1500                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1501                         {
1502                                         /* in normal playback, just start at the next zone. */
1503                                 start = i->first;
1504
1505                                         /* size is not 64bit! */
1506                                 if ((i->second - i->first) > max)
1507                                         size = max;
1508                                 else
1509                                         size = aligned_end - aligned_start;
1510
1511                                 eDebug("skip");
1512                                 if (m_skipmode_m < 0)
1513                                 {
1514                                         eDebug("reached SOF");
1515                                                 /* reached SOF */
1516                                         m_skipmode_m = 0;
1517                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1518                                 }
1519                         } else
1520                         {
1521                                         /* when skipping reverse, however, choose the zone before. */
1522                                 --i;
1523                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1524                                 size_t len;
1525
1526                                 aligned_start = align(i->first, blocksize);
1527                                 aligned_end = align(i->second, blocksize);
1528
1529                                 if ((aligned_end - aligned_start) > max)
1530                                         len = max;
1531                                 else
1532                                         len = aligned_end - aligned_start;
1533
1534                                 start = aligned_end - len;
1535                                 eDebug("skipping to %llx, %zd", start, len);
1536                         }
1537
1538                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1539                         return;
1540                 }
1541         }
1542
1543         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1544         {
1545                 eDebug("reached SOF");
1546                 m_skipmode_m = 0;
1547                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1548         }
1549
1550         if (m_source_span.empty())
1551         {
1552                 start = current_offset;
1553                 size = max;
1554                 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1555         } else
1556         {
1557                 start = current_offset;
1558                 size = 0;
1559         }
1560         return;
1561 }
1562
1563 void eDVBChannel::AddUse()
1564 {
1565         if (++m_use_count > 1 && m_state == state_last_instance)
1566         {
1567                 m_state = state_ok;
1568                 m_stateChanged(this);
1569         }
1570 }
1571
1572 void eDVBChannel::ReleaseUse()
1573 {
1574         if (!--m_use_count)
1575         {
1576                 m_state = state_release;
1577                 m_stateChanged(this);
1578         }
1579         else if (m_use_count == 1)
1580         {
1581                 m_state = state_last_instance;
1582                 m_stateChanged(this);
1583         }
1584 }
1585
1586 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1587 {
1588         if (m_channel_id)
1589                 m_mgr->removeChannel(this);
1590
1591         if (!channelid)
1592                 return 0;
1593
1594         if (!m_frontend)
1595         {
1596                 eDebug("no frontend to tune!");
1597                 return -ENODEV;
1598         }
1599
1600         m_channel_id = channelid;
1601         m_mgr->addChannel(channelid, this);
1602         m_state = state_tuning;
1603                         /* if tuning fails, shutdown the channel immediately. */
1604         int res;
1605         res = m_frontend->get().tune(*feparm);
1606         m_current_frontend_parameters = feparm;
1607
1608         if (res)
1609         {
1610                 m_state = state_release;
1611                 m_stateChanged(this);
1612                 return res;
1613         }
1614
1615         return 0;
1616 }
1617
1618 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1619 {
1620         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1621         return 0;
1622 }
1623
1624 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1625 {
1626         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1627         return 0;
1628 }
1629
1630 RESULT eDVBChannel::getState(int &state)
1631 {
1632         state = m_state;
1633         return 0;
1634 }
1635
1636 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1637 {
1638         return -1;
1639 }
1640
1641 void eDVBChannel::SDTready(int result)
1642 {
1643         ePyObject args = PyTuple_New(2), ret;
1644         bool ok=false;
1645         if (!result)
1646         {
1647                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1648                 {
1649                         ok = true;
1650                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1651                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1652                         break;
1653                 }
1654         }
1655         if (!ok)
1656         {
1657                 PyTuple_SET_ITEM(args, 0, Py_None);
1658                 PyTuple_SET_ITEM(args, 1, Py_None);
1659                 Py_INCREF(Py_None);
1660                 Py_INCREF(Py_None);
1661         }
1662         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1663         if (ret)
1664                 Py_DECREF(ret);
1665         Py_DECREF(args);
1666         Py_DECREF(m_tsid_onid_callback);
1667         m_tsid_onid_callback = ePyObject();
1668         m_tsid_onid_demux = 0;
1669         m_SDT = 0;
1670 }
1671
1672 int eDVBChannel::reserveDemux()
1673 {
1674         ePtr<iDVBDemux> dmx;
1675         if (!getDemux(dmx, 0))
1676         {
1677                 uint8_t id;
1678                 if (!dmx->getCADemuxID(id))
1679                         return id;
1680         }
1681         return -1;
1682 }
1683
1684 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1685 {
1686         if (PyCallable_Check(callback))
1687         {
1688                 if (!getDemux(m_tsid_onid_demux, 0))
1689                 {
1690                         m_SDT = new eTable<ServiceDescriptionSection>;
1691                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1692                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1693                         {
1694                                 m_tsid_onid_demux = 0;
1695                                 m_SDT = 0;
1696                         }
1697                         else
1698                         {
1699                                 Py_INCREF(callback);
1700                                 m_tsid_onid_callback = callback;
1701                                 return 0;
1702                         }
1703                 }
1704         }
1705         return -1;
1706 }
1707
1708 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1709 {
1710         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1711
1712         if (!our_demux)
1713         {
1714                 demux = 0;
1715
1716                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1717                         return -1;
1718
1719                 demux = *our_demux;
1720
1721                 /* don't hold a reference to the decoding demux, we don't need it. */
1722
1723                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1724                    the refcount is lost. thus, decoding demuxes are never allocated.
1725
1726                    this poses a big problem for PiP. */
1727
1728                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1729                         ;
1730                 else if (cap & capDecode)
1731                         our_demux = 0;
1732         }
1733         else
1734                 demux = *our_demux;
1735
1736         return 0;
1737 }
1738
1739 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1740 {
1741         frontend = 0;
1742         if (!m_frontend)
1743                 return -ENODEV;
1744         frontend = &m_frontend->get();
1745         if (frontend)
1746                 return 0;
1747         return -ENODEV;
1748 }
1749
1750 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1751 {
1752         param = m_current_frontend_parameters;
1753         return 0;
1754 }
1755
1756 RESULT eDVBChannel::playFile(const char *file)
1757 {
1758         eRawFile *f = new eRawFile();
1759         ePtr<iTsSource> source = f;
1760
1761         if (f->open(file) < 0)
1762         {
1763                 eDebug("can't open PVR file %s (%m)", file);
1764                 return -ENOENT;
1765         }
1766
1767         return playSource(source, file);
1768 }
1769
1770 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1771 {
1772         ASSERT(!m_frontend);
1773         if (m_pvr_thread)
1774         {
1775                 m_pvr_thread->stop();
1776                 delete m_pvr_thread;
1777                 m_pvr_thread = 0;
1778         }
1779
1780         if (!source->valid())
1781         {
1782                 eDebug("PVR source is not valid!");
1783                 return -ENOENT;
1784         }
1785
1786         m_tstools.setSource(source, streaminfo_file);
1787
1788                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1789                    THEN DO A REAL FIX HERE! */
1790
1791         if (m_pvr_fd_dst < 0)
1792         {
1793                 /* (this codepath needs to be improved anyway.) */
1794 #if HAVE_DVB_API_VERSION < 3
1795                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1796                 if (m_pvr_fd_dst < 0)
1797                 {
1798                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1799                         return -ENODEV;
1800                 }
1801 #else
1802                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1803                 if (demux)
1804                 {
1805                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1806                         if (m_pvr_fd_dst < 0)
1807                         {
1808                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1809                                 return -ENODEV;
1810                         }
1811                 }
1812                 else
1813                 {
1814                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1815                         return -ENODEV;
1816                 }
1817 #endif
1818         }
1819
1820         m_pvr_thread = new eDVBChannelFilePush();
1821         m_pvr_thread->enablePVRCommit(1);
1822         m_pvr_thread->setStreamMode(1);
1823         m_pvr_thread->setScatterGather(this);
1824
1825         m_event(this, evtPreStart);
1826
1827         m_pvr_thread->start(source, m_pvr_fd_dst);
1828         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1829
1830         m_state = state_ok;
1831         m_stateChanged(this);
1832
1833         return 0;
1834 }
1835
1836 void eDVBChannel::stopSource()
1837 {
1838         if (m_pvr_thread)
1839         {
1840                 m_pvr_thread->stop();
1841                 delete m_pvr_thread;
1842                 m_pvr_thread = 0;
1843         }
1844         if (m_pvr_fd_dst >= 0)
1845                 ::close(m_pvr_fd_dst);
1846         ePtr<iTsSource> d;
1847         m_tstools.setSource(d);
1848 }
1849
1850 void eDVBChannel::stopFile()
1851 {
1852         stopSource();
1853 }
1854
1855 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1856 {
1857         m_conn_cueSheetEvent = 0;
1858         m_cue = cuesheet;
1859         if (m_cue)
1860                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1861 }
1862
1863 RESULT eDVBChannel::getLength(pts_t &len)
1864 {
1865         return m_tstools.calcLen(len);
1866 }
1867
1868 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1869 {
1870         if (!decoding_demux)
1871                 return -1;
1872
1873         pts_t now;
1874
1875         int r;
1876
1877         if (mode == 0) /* demux */
1878         {
1879                 r = decoding_demux->getSTC(now, 0);
1880                 if (r)
1881                 {
1882                         eDebug("demux getSTC failed");
1883                         return -1;
1884                 }
1885         } else
1886                 now = pos; /* fixup supplied */
1887
1888         off_t off = 0; /* TODO: fixme */
1889         r = m_tstools.fixupPTS(off, now);
1890         if (r)
1891         {
1892                 eDebug("fixup PTS failed");
1893                 return -1;
1894         }
1895
1896         pos = now;
1897
1898         return 0;
1899 }
1900
1901 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1902 {
1903                         /* when seeking, we have to ensure that all buffers are flushed.
1904                            there are basically 3 buffers:
1905                            a.) the filepush's internal buffer
1906                            b.) the PVR buffer (before demux)
1907                            c.) the ratebuffer (after demux)
1908
1909                            it's important to clear them in the correct order, otherwise
1910                            the ratebuffer (for example) would immediately refill from
1911                            the not-yet-flushed PVR buffer.
1912                         */
1913
1914         m_pvr_thread->pause();
1915                 /* flush internal filepush buffer */
1916         m_pvr_thread->flush();
1917                 /* HACK: flush PVR buffer */
1918         ::ioctl(m_pvr_fd_dst, 0);
1919
1920                 /* flush ratebuffers (video, audio) */
1921         if (decoding_demux)
1922                 decoding_demux->flush();
1923
1924                 /* demux will also flush all decoder.. */
1925                 /* resume will re-query the SG */
1926         m_pvr_thread->resume();
1927 }
1928
1929 DEFINE_REF(eCueSheet);
1930
1931 eCueSheet::eCueSheet()
1932 {
1933         m_skipmode_ratio = 0;
1934 }
1935
1936 void eCueSheet::seekTo(int relative, const pts_t &pts)
1937 {
1938         m_lock.WrLock();
1939         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1940         m_lock.Unlock();
1941         m_event(evtSeek);
1942 }
1943
1944 void eCueSheet::clear()
1945 {
1946         m_lock.WrLock();
1947         m_spans.clear();
1948         m_lock.Unlock();
1949 }
1950
1951 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1952 {
1953         ASSERT(begin < end);
1954         m_lock.WrLock();
1955         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1956         m_lock.Unlock();
1957 }
1958
1959 void eCueSheet::commitSpans()
1960 {
1961         m_event(evtSpanChanged);
1962 }
1963
1964 void eCueSheet::setSkipmode(const pts_t &ratio)
1965 {
1966         m_lock.WrLock();
1967         m_skipmode_ratio = ratio;
1968         m_lock.Unlock();
1969         m_event(evtSkipmode);
1970 }
1971
1972 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1973 {
1974         m_decoding_demux = demux;
1975         m_decoder = decoder;
1976 }
1977
1978 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1979 {
1980         connection = new eConnection(this, m_event.connect(event));
1981         return 0;
1982 }