auto tuner selection is now working (this breaks allocateRawChannel..)
[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
201                 if (!adapter->getFrontend(frontend, i))
202                 {
203                         frontend->setSEC(m_sec);
204                         m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
205                 }
206         }
207 }
208
209 RESULT eDVBResourceManager::allocateFrontend(ePtr<iDVBFrontendParameters> &feparm, ePtr<eDVBAllocatedFrontend> &fe)
210 {
211         ePtr<eDVBRegisteredFrontend> best;
212         int bestval = 0;
213
214         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
215                 if (!i->m_inuse)
216                 {
217                         int c = i->m_frontend->isCompatibleWith(feparm);
218                         if (c > bestval)
219                         {
220                                 c = bestval;
221                                 best = i;
222                         }
223                 }
224
225         if (best)
226         {
227                 fe = new eDVBAllocatedFrontend(best);
228                 return 0;
229         }
230         
231         fe = 0;
232         
233         return -1;
234 }
235
236 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
237 {
238                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
239                    never use the first one unless we need a decoding demux. */
240
241         eDebug("allocate demux");
242         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
243         
244         if (i == m_demux.end())
245                 return -1;
246                 
247         int n=0;
248                 /* FIXME: hardware demux policy */
249         if (!(cap & iDVBChannel::capDecode))
250                 ++i, ++n;
251         
252         for (; i != m_demux.end(); ++i, ++n)
253                 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
254                 {
255                         if ((cap & iDVBChannel::capDecode) && n)
256                                 continue;
257                         
258                         demux = new eDVBAllocatedDemux(i);
259                         if (fe)
260                                 demux->get().setSourceFrontend(fe->m_frontend->getID());
261                         else
262                                 demux->get().setSourcePVR(0);
263                         return 0;
264                 }
265         eDebug("demux not found");
266         return -1;
267 }
268
269 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
270 {
271         m_list = list;
272         return 0;
273 }
274
275 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
276 {
277         list = m_list;
278         if (list)
279                 return 0;
280         else
281                 return -ENOENT;
282 }
283
284
285 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
286 {
287                 /* first, check if a channel is already existing. */
288         
289 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
290         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
291         {
292 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
293                 if (i->m_channel_id == channelid)
294                 {
295 //                      eDebug("found shared channel..");
296                         channel = i->m_channel;
297                         return 0;
298                 }
299         }
300         
301         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
302
303         if (!m_list)
304         {
305                 eDebug("no channel list set!");
306                 return -ENOENT;
307         }
308
309         ePtr<iDVBFrontendParameters> feparm;
310         if (m_list->getChannelFrontendData(channelid, feparm))
311         {
312                 eDebug("channel not found!");
313                 return -ENOENT;
314         }
315
316         /* allocate a frontend. */
317         
318         ePtr<eDVBAllocatedFrontend> fe;
319         
320         if (allocateFrontend(feparm, fe))
321                 return errNoFrontend;
322         
323 // will be allocated on demand:
324 //      ePtr<eDVBAllocatedDemux> demux;
325 //      
326 //      if (allocateDemux(*fe, demux))
327 //              return errNoDemux;
328
329         RESULT res;
330         ePtr<eDVBChannel> ch;
331         ch = new eDVBChannel(this, fe);
332
333         res = ch->setChannel(channelid, feparm);
334         if (res)
335         {
336                 channel = 0;
337                 return errChidNotFound;
338         }
339         
340         channel = ch;
341         return 0;
342 }
343
344 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
345 {
346         ePtr<eDVBAllocatedFrontend> fe;
347
348 #warning FIXME allocateRawChannel
349
350 //      if (allocateFrontend(eDVBChannelID(), fe))
351                 return errNoFrontend;
352         
353 //      ePtr<eDVBAllocatedDemux> demux;
354         //
355 //      if (allocateDemux(*fe, demux))
356 //              return errNoDemux;
357         
358         eDVBChannel *ch;
359         ch = new eDVBChannel(this, fe);
360
361         channel = ch;
362         return 0;
363 }
364
365
366 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
367 {
368         ePtr<eDVBAllocatedDemux> demux;
369         
370 //      if (allocateDemux(0, demux))
371 //              return errNoDemux;
372         
373         eDVBChannel *ch;
374         ch = new eDVBChannel(this, 0);
375         
376         channel = ch;
377         return 0;
378 }
379
380 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
381 {
382         m_active_channels.push_back(active_channel(chid, ch));
383         /* emit */ m_channelAdded(ch);
384         return 0;
385 }
386
387 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
388 {
389         int cnt = 0;
390         for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
391         {
392                 if (i->m_channel == ch)
393                 {
394                         i = m_active_channels.erase(i);
395                         ++cnt;
396                 } else
397                         ++i;
398         }
399         ASSERT(cnt == 1);
400         if (cnt == 1)
401                 return 0;
402         return -ENOENT;
403 }
404
405 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
406 {
407         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
408         return 0;
409 }
410
411 DEFINE_REF(eDVBChannel);
412
413 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
414 {
415         m_frontend = frontend;
416
417         m_pvr_thread = 0;
418         
419         if (m_frontend)
420                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
421 }
422
423 eDVBChannel::~eDVBChannel()
424 {
425         if (m_channel_id)
426                 m_mgr->removeChannel(this);
427         
428         if (m_pvr_thread)
429         {
430                 m_pvr_thread->stop();
431                 ::close(m_pvr_fd_src);
432                 ::close(m_pvr_fd_dst);
433                 delete m_pvr_thread;
434         }
435 }
436
437 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
438 {
439         int state, ourstate = 0;
440         
441                 /* if we are already in shutdown, don't change state. */
442         if (m_state == state_release)
443                 return;
444         
445         if (fe->getState(state))
446                 return;
447         
448         if (state == iDVBFrontend::stateLock)
449         {
450                 eDebug("OURSTATE: ok");
451                 ourstate = state_ok;
452         } else if (state == iDVBFrontend::stateTuning)
453         {
454                 eDebug("OURSTATE: tuning");
455                 ourstate = state_tuning;
456         } else if (state == iDVBFrontend::stateLostLock)
457         {
458                 eDebug("OURSTATE: lost lock");
459                 ourstate = state_unavailable;
460         } else if (state == iDVBFrontend::stateFailed)
461         {
462                 eDebug("OURSTATE: failed");
463                 ourstate = state_failed;
464         } else
465                 eFatal("state unknown");
466         
467         if (ourstate != m_state)
468         {
469                 m_state = ourstate;
470                 m_stateChanged(this);
471         }
472 }
473
474 void eDVBChannel::AddUse()
475 {
476         ++m_use_count;
477 }
478
479 void eDVBChannel::ReleaseUse()
480 {
481         if (!--m_use_count)
482         {
483                 m_state = state_release;
484                 m_stateChanged(this);
485         }
486 }
487
488 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
489 {
490         if (m_channel_id)
491                 m_mgr->removeChannel(this);
492                 
493         if (!channelid)
494                 return 0;
495
496         if (!m_frontend)
497         {
498                 eDebug("no frontend to tune!");
499                 return -ENODEV;
500         }
501         
502         m_channel_id = channelid;
503         m_mgr->addChannel(channelid, this);
504         m_state = state_tuning;
505                         /* if tuning fails, shutdown the channel immediately. */
506         int res;
507         res = m_frontend->get().tune(*feparm);
508         
509         if (res)
510         {
511                 m_state = state_release;
512                 m_stateChanged(this);
513                 return res;
514         }
515         
516         return 0;
517 }
518
519 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
520 {
521         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
522         return 0;
523 }
524
525 RESULT eDVBChannel::getState(int &state)
526 {
527         state = m_state;
528         return 0;
529 }
530
531 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
532 {
533         return -1;
534 }
535
536 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
537 {
538         eDebug("get %d demux", cap);
539         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
540         
541         if (!our_demux)
542         {
543                 demux = 0;
544                 
545                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
546                         return -1;
547                 
548         }
549         
550         demux = *our_demux;
551         if (cap & capDecode)
552         {
553                 our_demux = 0;
554         }
555         return 0;
556 }
557
558 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
559 {
560         frontend = &m_frontend->get();
561         if (frontend)
562                 return 0;
563         else
564                 return -ENODEV;
565 }
566
567 RESULT eDVBChannel::playFile(const char *file)
568 {
569         ASSERT(!m_frontend);
570         if (m_pvr_thread)
571         {
572                 m_pvr_thread->stop();
573                 delete m_pvr_thread;
574                 m_pvr_thread = 0;
575         }
576         
577         m_tstools.openFile(file);
578         
579                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
580                    THEN DO A REAL FIX HERE! */
581         
582                 /* (this codepath needs to be improved anyway.) */
583         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
584         if (m_pvr_fd_dst < 0)
585         {
586                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
587                 return -ENODEV;
588         }
589         
590         m_pvr_fd_src = open(file, O_RDONLY);
591         if (m_pvr_fd_src < 0)
592         {
593                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
594                 close(m_pvr_fd_dst);
595                 return -ENOENT;
596         }
597         
598         m_state = state_ok;
599         m_stateChanged(this);
600         
601         m_pvr_thread = new eFilePushThread();
602         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
603
604         return 0;
605 }
606
607 RESULT eDVBChannel::getLength(pts_t &len)
608 {
609         return m_tstools.calcLen(len);
610 }
611
612 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
613 {
614         if (!m_decoder_demux)
615                 return -1;
616         
617         off_t begin = 0;
618                 /* getPTS for offset 0 is cached, so it doesn't harm. */
619         int r = m_tstools.getPTS(begin, pos);
620         if (r)
621         {
622                 eDebug("tstools getpts(0) failed!");
623                 return r;
624         }
625         
626         pts_t now;
627         
628         r = m_decoder_demux->get().getSTC(now);
629
630         if (r)
631         {
632                 eDebug("demux getSTC failed");
633                 return -1;
634         }
635         
636 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
637                 /* when we are less than 10 seconds before the start, return 0. */
638                 /* (we're just waiting for the timespam to start) */
639         if ((now < pos) && ((pos - now) < 90000 * 10))
640         {
641                 pos = 0;
642                 return 0;
643         }
644         
645         if (now < pos) /* wrap around */
646                 pos = now + ((pts_t)1)<<33 - pos;
647         else
648                 pos = now - pos;
649         
650         return 0;
651 }
652
653 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
654 {
655         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
656         
657         if (bitrate == -1)
658                 return -1;
659         
660         if (relative)
661         {
662                 pts_t now;
663                 if (getCurrentPosition(now))
664                 {
665                         eDebug("seekTo: getCurrentPosition failed!");
666                         return -1;
667                 }
668                 pts += now;
669         }
670         
671         if (pts < 0)
672                 pts = 0;
673         
674         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
675         
676         seekToPosition(offset);
677         return 0;
678 }
679
680 RESULT eDVBChannel::seekToPosition(const off_t &r)
681 {
682                         /* when seeking, we have to ensure that all buffers are flushed.
683                            there are basically 3 buffers:
684                            a.) the filepush's internal buffer
685                            b.) the PVR buffer (before demux)
686                            c.) the ratebuffer (after demux)
687                            
688                            it's important to clear them in the correct order, otherwise
689                            the ratebuffer (for example) would immediately refill from
690                            the not-yet-flushed PVR buffer.
691                         */
692         eDebug("eDVBChannel: seekToPosition .. %llx", r);
693         m_pvr_thread->pause();
694
695                 /* flush internal filepush buffer */
696         m_pvr_thread->flush();
697
698                 /* HACK: flush PVR buffer */
699         ::ioctl(m_pvr_fd_dst, 0);
700         
701                 /* flush ratebuffers (video, audio) */
702         if (m_decoder_demux)
703                 m_decoder_demux->get().flush();
704
705                 /* demux will also flush all decoder.. */
706         m_pvr_thread->seek(SEEK_SET, r);
707         m_pvr_thread->resume();
708         return 0;
709 }