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