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