By Anders Holst:
[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                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1466                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1467         }
1468
1469         m_cue->m_lock.Unlock();
1470
1471         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1472         {
1473                 long long aligned_start = align(i->first, blocksize);
1474                 long long aligned_end = align(i->second, blocksize);
1475
1476                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1477                 {
1478                         start = current_offset;
1479                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1480                         if ((aligned_end - current_offset) > max)
1481                                 size = max;
1482                         else
1483                                 size = aligned_end - current_offset;
1484                         eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1485                         return;
1486                 }
1487                 if (current_offset < aligned_start)
1488                 {
1489                                 /* ok, our current offset is in an 'out' zone. */
1490                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1491                         {
1492                                         /* in normal playback, just start at the next zone. */
1493                                 start = i->first;
1494
1495                                         /* size is not 64bit! */
1496                                 if ((i->second - i->first) > max)
1497                                         size = max;
1498                                 else
1499                                         size = aligned_end - aligned_start;
1500
1501                                 eDebug("skip");
1502                                 if (m_skipmode_m < 0)
1503                                 {
1504                                         eDebug("reached SOF");
1505                                                 /* reached SOF */
1506                                         m_skipmode_m = 0;
1507                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1508                                 }
1509                         } else
1510                         {
1511                                         /* when skipping reverse, however, choose the zone before. */
1512                                 --i;
1513                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1514                                 size_t len;
1515
1516                                 aligned_start = align(i->first, blocksize);
1517                                 aligned_end = align(i->second, blocksize);
1518
1519                                 if ((aligned_end - aligned_start) > max)
1520                                         len = max;
1521                                 else
1522                                         len = aligned_end - aligned_start;
1523
1524                                 start = aligned_end - len;
1525                                 eDebug("skipping to %llx, %d", start, len);
1526                         }
1527
1528                         eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1529                         return;
1530                 }
1531         }
1532
1533         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1534         {
1535                 eDebug("reached SOF");
1536                 m_skipmode_m = 0;
1537                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1538         }
1539
1540         if (m_source_span.empty())
1541         {
1542                 start = current_offset;
1543                 size = max;
1544                 eDebug("NO CUESHEET. (%08llx, %d)", start, size);
1545         } else
1546         {
1547                 start = current_offset;
1548                 size = 0;
1549         }
1550         return;
1551 }
1552
1553 void eDVBChannel::AddUse()
1554 {
1555         if (++m_use_count > 1 && m_state == state_last_instance)
1556         {
1557                 m_state = state_ok;
1558                 m_stateChanged(this);
1559         }
1560 }
1561
1562 void eDVBChannel::ReleaseUse()
1563 {
1564         if (!--m_use_count)
1565         {
1566                 m_state = state_release;
1567                 m_stateChanged(this);
1568         }
1569         else if (m_use_count == 1)
1570         {
1571                 m_state = state_last_instance;
1572                 m_stateChanged(this);
1573         }
1574 }
1575
1576 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1577 {
1578         if (m_channel_id)
1579                 m_mgr->removeChannel(this);
1580
1581         if (!channelid)
1582                 return 0;
1583
1584         if (!m_frontend)
1585         {
1586                 eDebug("no frontend to tune!");
1587                 return -ENODEV;
1588         }
1589
1590         m_channel_id = channelid;
1591         m_mgr->addChannel(channelid, this);
1592         m_state = state_tuning;
1593                         /* if tuning fails, shutdown the channel immediately. */
1594         int res;
1595         res = m_frontend->get().tune(*feparm);
1596         m_current_frontend_parameters = feparm;
1597
1598         if (res)
1599         {
1600                 m_state = state_release;
1601                 m_stateChanged(this);
1602                 return res;
1603         }
1604
1605         return 0;
1606 }
1607
1608 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1609 {
1610         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1611         return 0;
1612 }
1613
1614 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1615 {
1616         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1617         return 0;
1618 }
1619
1620 RESULT eDVBChannel::getState(int &state)
1621 {
1622         state = m_state;
1623         return 0;
1624 }
1625
1626 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1627 {
1628         return -1;
1629 }
1630
1631 void eDVBChannel::SDTready(int result)
1632 {
1633         ePyObject args = PyTuple_New(2), ret;
1634         bool ok=false;
1635         if (!result)
1636         {
1637                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1638                 {
1639                         ok = true;
1640                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1641                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1642                         break;
1643                 }
1644         }
1645         if (!ok)
1646         {
1647                 PyTuple_SET_ITEM(args, 0, Py_None);
1648                 PyTuple_SET_ITEM(args, 1, Py_None);
1649                 Py_INCREF(Py_None);
1650                 Py_INCREF(Py_None);
1651         }
1652         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1653         if (ret)
1654                 Py_DECREF(ret);
1655         Py_DECREF(args);
1656         Py_DECREF(m_tsid_onid_callback);
1657         m_tsid_onid_callback = ePyObject();
1658         m_tsid_onid_demux = 0;
1659         m_SDT = 0;
1660 }
1661
1662 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1663 {
1664         if (PyCallable_Check(callback))
1665         {
1666                 if (!getDemux(m_tsid_onid_demux, 0))
1667                 {
1668                         m_SDT = new eTable<ServiceDescriptionSection>;
1669                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1670                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1671                         {
1672                                 m_tsid_onid_demux = 0;
1673                                 m_SDT = 0;
1674                         }
1675                         else
1676                         {
1677                                 Py_INCREF(callback);
1678                                 m_tsid_onid_callback = callback;
1679                                 return 0;
1680                         }
1681                 }
1682         }
1683         return -1;
1684 }
1685
1686 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1687 {
1688         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1689
1690         if (!our_demux)
1691         {
1692                 demux = 0;
1693
1694                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1695                         return -1;
1696
1697                 demux = *our_demux;
1698
1699                 /* don't hold a reference to the decoding demux, we don't need it. */
1700
1701                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1702                    the refcount is lost. thus, decoding demuxes are never allocated.
1703
1704                    this poses a big problem for PiP. */
1705
1706                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1707                         ;
1708                 else if (cap & capDecode)
1709                         our_demux = 0;
1710         }
1711         else
1712                 demux = *our_demux;
1713
1714         return 0;
1715 }
1716
1717 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1718 {
1719         frontend = 0;
1720         if (!m_frontend)
1721                 return -ENODEV;
1722         frontend = &m_frontend->get();
1723         if (frontend)
1724                 return 0;
1725         return -ENODEV;
1726 }
1727
1728 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1729 {
1730         param = m_current_frontend_parameters;
1731         return 0;
1732 }
1733
1734 RESULT eDVBChannel::playFile(const char *file)
1735 {
1736         ASSERT(!m_frontend);
1737         if (m_pvr_thread)
1738         {
1739                 m_pvr_thread->stop();
1740                 delete m_pvr_thread;
1741                 m_pvr_thread = 0;
1742         }
1743
1744         m_tstools.openFile(file);
1745
1746                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1747                    THEN DO A REAL FIX HERE! */
1748
1749         if (m_pvr_fd_dst < 0)
1750         {
1751                 /* (this codepath needs to be improved anyway.) */
1752 #if HAVE_DVB_API_VERSION < 3
1753                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1754 #else
1755                 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1756 #endif
1757                 if (m_pvr_fd_dst < 0)
1758                 {
1759                         eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1760                         return -ENODEV;
1761                 }
1762         }
1763
1764         m_pvr_thread = new eDVBChannelFilePush();
1765         m_pvr_thread->enablePVRCommit(1);
1766         m_pvr_thread->setStreamMode(1);
1767         m_pvr_thread->setScatterGather(this);
1768
1769         if (m_pvr_thread->start(file, m_pvr_fd_dst))
1770         {
1771                 delete m_pvr_thread;
1772                 m_pvr_thread = 0;
1773                 ::close(m_pvr_fd_dst);
1774                 m_pvr_fd_dst = -1;
1775                 eDebug("can't open PVR file %s (%m)", file);
1776                 return -ENOENT;
1777         }
1778         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1779
1780         m_state = state_ok;
1781         m_stateChanged(this);
1782
1783         return 0;
1784 }
1785
1786 void eDVBChannel::stopFile()
1787 {
1788         if (m_pvr_thread)
1789         {
1790                 m_pvr_thread->stop();
1791                 delete m_pvr_thread;
1792                 m_pvr_thread = 0;
1793         }
1794         if (m_pvr_fd_dst >= 0)
1795                 ::close(m_pvr_fd_dst);
1796 }
1797
1798 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1799 {
1800         m_conn_cueSheetEvent = 0;
1801         m_cue = cuesheet;
1802         if (m_cue)
1803                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1804 }
1805
1806 RESULT eDVBChannel::getLength(pts_t &len)
1807 {
1808         return m_tstools.calcLen(len);
1809 }
1810
1811 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1812 {
1813         if (!decoding_demux)
1814                 return -1;
1815
1816         pts_t now;
1817
1818         int r;
1819
1820         if (mode == 0) /* demux */
1821         {
1822                 r = decoding_demux->getSTC(now, 0);
1823                 if (r)
1824                 {
1825                         eDebug("demux getSTC failed");
1826                         return -1;
1827                 }
1828         } else
1829                 now = pos; /* fixup supplied */
1830
1831         off_t off = 0; /* TODO: fixme */
1832         r = m_tstools.fixupPTS(off, now);
1833         if (r)
1834         {
1835                 eDebug("fixup PTS failed");
1836                 return -1;
1837         }
1838
1839         pos = now;
1840
1841         return 0;
1842 }
1843
1844 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1845 {
1846                         /* when seeking, we have to ensure that all buffers are flushed.
1847                            there are basically 3 buffers:
1848                            a.) the filepush's internal buffer
1849                            b.) the PVR buffer (before demux)
1850                            c.) the ratebuffer (after demux)
1851
1852                            it's important to clear them in the correct order, otherwise
1853                            the ratebuffer (for example) would immediately refill from
1854                            the not-yet-flushed PVR buffer.
1855                         */
1856
1857         m_pvr_thread->pause();
1858                 /* flush internal filepush buffer */
1859         m_pvr_thread->flush();
1860                 /* HACK: flush PVR buffer */
1861         ::ioctl(m_pvr_fd_dst, 0);
1862
1863                 /* flush ratebuffers (video, audio) */
1864         if (decoding_demux)
1865                 decoding_demux->flush();
1866
1867                 /* demux will also flush all decoder.. */
1868                 /* resume will re-query the SG */
1869         m_pvr_thread->resume();
1870 }
1871
1872 DEFINE_REF(eCueSheet);
1873
1874 eCueSheet::eCueSheet()
1875 {
1876         m_skipmode_ratio = 0;
1877 }
1878
1879 void eCueSheet::seekTo(int relative, const pts_t &pts)
1880 {
1881         m_lock.WrLock();
1882         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1883         m_lock.Unlock();
1884         m_event(evtSeek);
1885 }
1886
1887 void eCueSheet::clear()
1888 {
1889         m_lock.WrLock();
1890         m_spans.clear();
1891         m_lock.Unlock();
1892 }
1893
1894 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1895 {
1896         ASSERT(begin < end);
1897         m_lock.WrLock();
1898         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1899         m_lock.Unlock();
1900 }
1901
1902 void eCueSheet::commitSpans()
1903 {
1904         m_event(evtSpanChanged);
1905 }
1906
1907 void eCueSheet::setSkipmode(const pts_t &ratio)
1908 {
1909         m_lock.WrLock();
1910         m_skipmode_ratio = ratio;
1911         m_lock.Unlock();
1912         m_event(evtSkipmode);
1913 }
1914
1915 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1916 {
1917         m_decoding_demux = demux;
1918         m_decoder = decoder;
1919 }
1920
1921 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1922 {
1923         connection = new eConnection(this, m_event.connect(event));
1924         return 0;
1925 }