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