work around capDecode problem
[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/sec.h>
6
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
16
17 DEFINE_REF(eDVBAllocatedFrontend);
18
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
20 {
21         m_fe->m_inuse++;
22 }
23
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
25 {
26         --m_fe->m_inuse;
27 }
28
29 DEFINE_REF(eDVBAllocatedDemux);
30
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
32 {
33         m_demux->m_inuse++;
34 }
35
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
37 {
38         --m_demux->m_inuse;
39 }
40
41 DEFINE_REF(eDVBResourceManager);
42
43 eDVBResourceManager *eDVBResourceManager::instance;
44
45 eDVBResourceManager::eDVBResourceManager()
46 {
47         avail = 1;
48         busy = 0;
49         m_sec = new eDVBSatelliteEquipmentControl;
50         if (!instance)
51                 instance = this;
52                 
53                 /* search available adapters... */
54
55                 // add linux devices
56         
57         int num_adapter = 0;
58         while (eDVBAdapterLinux::exist(num_adapter))
59         {
60                 addAdapter(new eDVBAdapterLinux(num_adapter));
61                 num_adapter++;
62         }
63         
64         eDebug("found %d adapter, %d frontends and %d demux", 
65                 m_adapter.size(), m_frontend.size(), m_demux.size());
66 }
67
68
69 DEFINE_REF(eDVBAdapterLinux);
70 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
71 {
72                 // scan frontends
73         int num_fe = 0;
74         
75         eDebug("scanning for frontends..");
76         while (1)
77         {
78                 struct stat s;
79                 char filename[128];
80 #if HAVE_DVB_API_VERSION < 3
81                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
82 #else
83                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
84 #endif
85                 if (stat(filename, &s))
86                         break;
87                 ePtr<eDVBFrontend> fe;
88
89                 int ok = 0;
90                 fe = new eDVBFrontend(m_nr, num_fe, ok);
91                 if (ok)
92                         m_frontend.push_back(fe);
93                 ++num_fe;
94         }
95         
96                 // scan demux
97         int num_demux = 0;
98         while (1)
99         {
100                 struct stat s;
101                 char filename[128];
102 #if HAVE_DVB_API_VERSION < 3
103                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
104 #else
105                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
106 #endif
107                 if (stat(filename, &s))
108                         break;
109                 ePtr<eDVBDemux> demux;
110                 
111                 demux = new eDVBDemux(m_nr, num_demux);
112                 m_demux.push_back(demux);
113                         
114                 ++num_demux;
115         }
116 }
117
118 int eDVBAdapterLinux::getNumDemux()
119 {
120         return m_demux.size();
121 }
122
123 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
124 {
125         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
126         while (nr && (i != m_demux.end()))
127         {
128                 --nr;
129                 ++i;
130         }
131         
132         if (i != m_demux.end())
133                 demux = *i;
134         else
135                 return -1;
136                 
137         return 0;
138 }
139
140 int eDVBAdapterLinux::getNumFrontends()
141 {
142         return m_frontend.size();
143 }
144
145 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
146 {
147         eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
148         while (nr && (i != m_frontend.end()))
149         {
150                 --nr;
151                 ++i;
152         }
153         
154         if (i != m_frontend.end())
155                 fe = *i;
156         else
157                 return -1;
158                 
159         return 0;
160 }
161
162 int eDVBAdapterLinux::exist(int nr)
163 {
164         struct stat s;
165         char filename[128];
166 #if HAVE_DVB_API_VERSION < 3
167         sprintf(filename, "/dev/dvb/card%d", nr);
168 #else
169         sprintf(filename, "/dev/dvb/adapter%d", nr);
170 #endif
171         if (!stat(filename, &s))
172                 return 1;
173         return 0;
174 }
175
176 eDVBResourceManager::~eDVBResourceManager()
177 {
178         if (instance == this)
179                 instance = 0;
180 }
181
182 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
183 {
184         int num_fe = adapter->getNumFrontends();
185         int num_demux = adapter->getNumDemux();
186         
187         m_adapter.push_back(adapter);
188         
189         int i;
190         for (i=0; i<num_demux; ++i)
191         {
192                 ePtr<eDVBDemux> demux;
193                 if (!adapter->getDemux(demux, i))
194                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
195         }
196
197         for (i=0; i<num_fe; ++i)
198         {
199                 ePtr<eDVBFrontend> frontend;
200                 if (!adapter->getFrontend(frontend, i))
201                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
202         }
203 }
204
205 RESULT eDVBResourceManager::allocateFrontend(const eDVBChannelID &chid, ePtr<eDVBAllocatedFrontend> &fe)
206 {
207                 /* find first unused frontend. we ignore compatibility for now. */
208         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
209                 if (!i->m_inuse)
210                 {
211                         fe = new eDVBAllocatedFrontend(i);
212                         return 0;
213                 }
214         return -1;
215 }
216
217 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
218 {
219                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
220                    never use the first one unless we need a decoding demux. */
221
222         eDebug("allocate demux");
223         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
224         
225         if (i == m_demux.end())
226                 return -1;
227                 
228         int n=0;
229                 /* FIXME: hardware demux policy */
230         if (!(cap & iDVBChannel::capDecode))
231                 ++i, ++n;
232         
233         for (; i != m_demux.end(); ++i, ++n)
234                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
235                 {
236                         if ((cap & iDVBChannel::capDecode) && n)
237                                 continue;
238                         
239                         demux = new eDVBAllocatedDemux(i);
240                         if (fe)
241                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
242                         else
243                                 demux->get().setSourcePVR(0);
244                         eDebug("demux (%d) found (fe id: %d)", n, fe->m_frontend->getID());
245                         return 0;
246                 }
247         eDebug("demux not found");
248         return -1;
249 }
250
251 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
252 {
253         m_list = list;
254         return 0;
255 }
256
257 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
258 {
259         list = m_list;
260         if (list)
261                 return 0;
262         else
263                 return -ENOENT;
264 }
265
266
267 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
268 {
269                 /* first, check if a channel is already existing. */
270         
271 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
272         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
273         {
274 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
275                 if (i->m_channel_id == channelid)
276                 {
277 //                      eDebug("found shared channel..");
278                         channel = i->m_channel;
279                         return 0;
280                 }
281         }
282         
283                 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
284                 
285                 /* allocate a frontend. */
286         
287         ePtr<eDVBAllocatedFrontend> fe;
288         
289         if (allocateFrontend(channelid, fe))
290                 return errNoFrontend;
291         
292 // will be allocated on demand:
293 //      ePtr<eDVBAllocatedDemux> demux;
294 //      
295 //      if (allocateDemux(*fe, demux))
296 //              return errNoDemux;
297         
298         RESULT res;
299         ePtr<eDVBChannel> ch;
300         ch = new eDVBChannel(this, fe);
301
302         ePtr<iDVBFrontend> myfe;
303         if (!ch->getFrontend(myfe))
304                 myfe->setSEC(m_sec);
305
306         res = ch->setChannel(channelid);
307         if (res)
308         {
309                 channel = 0;
310                 return errChidNotFound;
311         }
312         
313         channel = ch;
314         return 0;
315 }
316
317 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
318 {
319         ePtr<eDVBAllocatedFrontend> fe;
320         
321         if (allocateFrontend(eDVBChannelID(), fe))
322                 return errNoFrontend;
323         
324 //      ePtr<eDVBAllocatedDemux> demux;
325         //
326 //      if (allocateDemux(*fe, demux))
327 //              return errNoDemux;
328         
329         eDVBChannel *ch;
330         ch = new eDVBChannel(this, fe);
331
332         ePtr<iDVBFrontend> myfe;
333         if (!ch->getFrontend(myfe))
334                 myfe->setSEC(m_sec);
335
336         channel = ch;
337         return 0;
338 }
339
340
341 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
342 {
343         ePtr<eDVBAllocatedDemux> demux;
344         
345 //      if (allocateDemux(0, demux))
346 //              return errNoDemux;
347         
348         eDVBChannel *ch;
349         ch = new eDVBChannel(this, 0);
350         
351         channel = ch;
352         return 0;
353 }
354
355 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
356 {
357         m_active_channels.push_back(active_channel(chid, ch));
358 //      /* emit */ m_channelAdded(ch);
359         return 0;
360 }
361
362 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
363 {
364         int cnt = 0;
365         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
366         {
367                 if (i->m_channel == ch)
368                 {
369                         i = m_active_channels.erase(i);
370                         ++cnt;
371                 } else
372                         ++i;
373         }
374         ASSERT(cnt == 1);
375         if (cnt == 1)
376                 return 0;
377         return -ENOENT;
378 }
379
380 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
381 {
382         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
383         return 0;
384 }
385
386 DEFINE_REF(eDVBChannel);
387
388 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
389 {
390         m_frontend = frontend;
391
392         m_pvr_thread = 0;
393         
394         if (m_frontend)
395                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
396 }
397
398 eDVBChannel::~eDVBChannel()
399 {
400         if (m_channel_id)
401                 m_mgr->removeChannel(this);
402         
403         if (m_pvr_thread)
404         {
405                 m_pvr_thread->stop();
406                 ::close(m_pvr_fd_src);
407                 ::close(m_pvr_fd_dst);
408                 delete m_pvr_thread;
409         }
410 }
411
412 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
413 {
414         int state, ourstate = 0;
415         
416                 /* if we are already in shutdown, don't change state. */
417         if (m_state == state_release)
418                 return;
419         
420         if (fe->getState(state))
421                 return;
422         
423         if (state == iDVBFrontend::stateLock)
424         {
425                 eDebug("OURSTATE: ok");
426                 ourstate = state_ok;
427         } else if (state == iDVBFrontend::stateTuning)
428         {
429                 eDebug("OURSTATE: tuning");
430                 ourstate = state_tuning;
431         } else if (state == iDVBFrontend::stateLostLock)
432         {
433                 eDebug("OURSTATE: lost lock");
434                 ourstate = state_unavailable;
435         } else if (state == iDVBFrontend::stateFailed)
436         {
437                 eDebug("OURSTATE: failed");
438                 ourstate = state_failed;
439         } else
440                 eFatal("state unknown");
441         
442         if (ourstate != m_state)
443         {
444                 m_state = ourstate;
445                 m_stateChanged(this);
446         }
447 }
448
449 void eDVBChannel::AddUse()
450 {
451         ++m_use_count;
452 }
453
454 void eDVBChannel::ReleaseUse()
455 {
456         if (!--m_use_count)
457         {
458                 m_state = state_release;
459                 m_stateChanged(this);
460         }
461 }
462
463 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
464 {
465         if (m_channel_id)
466                 m_mgr->removeChannel(this);
467                 
468         if (!channelid)
469                 return 0;
470
471         ePtr<iDVBChannelList> list;
472         
473         if (m_mgr->getChannelList(list))
474         {
475                 eDebug("no channel list set!");
476                 return -ENOENT;
477         }
478         
479         eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
480                 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
481
482         ePtr<iDVBFrontendParameters> feparm;
483         if (list->getChannelFrontendData(channelid, feparm))
484         {
485                 eDebug("channel not found!");
486                 return -ENOENT;
487         }
488         
489         if (!m_frontend)
490         {
491                 eDebug("no frontend to tune!");
492                 return -ENODEV;
493         }
494         
495         m_channel_id = channelid;
496         m_mgr->addChannel(channelid, this);
497         m_state = state_tuning;
498                         /* if tuning fails, shutdown the channel immediately. */
499         int res;
500         res = m_frontend->get().tune(*feparm);
501         
502         if (res)
503         {
504                 m_state = state_release;
505                 m_stateChanged(this);
506                 return res;
507         }
508         
509         return 0;
510 }
511
512 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
513 {
514         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
515         return 0;
516 }
517
518 RESULT eDVBChannel::getState(int &state)
519 {
520         state = m_state;
521         return 0;
522 }
523
524 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
525 {
526         return -1;
527 }
528
529 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
530 {
531         eDebug("get %d demux", cap);
532         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
533         
534         if (!our_demux)
535         {
536                 demux = 0;
537                 
538                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
539                         return -1;
540                 
541         }
542         
543         demux = *our_demux;
544         if (cap & capDecode)
545         {
546                 our_demux = 0;
547         }
548         return 0;
549 }
550
551 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
552 {
553         frontend = &m_frontend->get();
554         if (frontend)
555                 return 0;
556         else
557                 return -ENODEV;
558 }
559
560 RESULT eDVBChannel::playFile(const char *file)
561 {
562         ASSERT(!m_frontend);
563         if (m_pvr_thread)
564         {
565                 m_pvr_thread->stop();
566                 delete m_pvr_thread;
567                 m_pvr_thread = 0;
568         }
569         
570         m_tstools.openFile(file);
571         
572                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
573                    THEN DO A REAL FIX HERE! */
574         
575                 /* (this codepath needs to be improved anyway.) */
576         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
577         if (m_pvr_fd_dst < 0)
578         {
579                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
580                 return -ENODEV;
581         }
582         
583         m_pvr_fd_src = open(file, O_RDONLY);
584         if (m_pvr_fd_src < 0)
585         {
586                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
587                 close(m_pvr_fd_dst);
588                 return -ENOENT;
589         }
590         
591         m_state = state_ok;
592         m_stateChanged(this);
593         
594         m_pvr_thread = new eFilePushThread();
595         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
596
597         return 0;
598 }
599
600 RESULT eDVBChannel::getLength(pts_t &len)
601 {
602         return m_tstools.calcLen(len);
603 }
604
605 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
606 {
607         if (!m_decoder_demux)
608                 return -1;
609         
610         off_t begin = 0;
611                 /* getPTS for offset 0 is cached, so it doesn't harm. */
612         int r = m_tstools.getPTS(begin, pos);
613         if (r)
614         {
615                 eDebug("tstools getpts(0) failed!");
616                 return r;
617         }
618         
619         pts_t now;
620         
621         r = m_decoder_demux->get().getSTC(now);
622
623         if (r)
624         {
625                 eDebug("demux getSTC failed");
626                 return -1;
627         }
628         
629 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
630                 /* when we are less than 10 seconds before the start, return 0. */
631                 /* (we're just waiting for the timespam to start) */
632         if ((now < pos) && ((pos - now) < 90000 * 10))
633         {
634                 pos = 0;
635                 return 0;
636         }
637         
638         if (now < pos) /* wrap around */
639                 pos = now + ((pts_t)1)<<33 - pos;
640         else
641                 pos = now - pos;
642         
643         return 0;
644 }
645
646 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
647 {
648         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
649         
650         if (bitrate == -1)
651                 return -1;
652         
653         if (relative)
654         {
655                 pts_t now;
656                 if (getCurrentPosition(now))
657                 {
658                         eDebug("seekTo: getCurrentPosition failed!");
659                         return -1;
660                 }
661                 pts += now;
662         }
663         
664         if (pts < 0)
665                 pts = 0;
666         
667         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
668         
669         seekToPosition(offset);
670         return 0;
671 }
672
673 RESULT eDVBChannel::seekToPosition(const off_t &r)
674 {
675                         /* when seeking, we have to ensure that all buffers are flushed.
676                            there are basically 3 buffers:
677                            a.) the filepush's internal buffer
678                            b.) the PVR buffer (before demux)
679                            c.) the ratebuffer (after demux)
680                            
681                            it's important to clear them in the correct order, otherwise
682                            the ratebuffer (for example) would immediately refill from
683                            the not-yet-flushed PVR buffer.
684                         */
685         eDebug("eDVBChannel: seekToPosition .. %llx", r);
686         m_pvr_thread->pause();
687
688                 /* flush internal filepush buffer */
689         m_pvr_thread->flush();
690
691                 /* HACK: flush PVR buffer */
692         ::ioctl(m_pvr_fd_dst, 0);
693         
694                 /* flush ratebuffers (video, audio) */
695         if (m_decoder_demux)
696                 m_decoder_demux->get().flush();
697
698                 /* demux will also flush all decoder.. */
699         m_pvr_thread->seek(SEEK_SET, r);
700         m_pvr_thread->resume();
701         return 0;
702 }