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