add - untested - multituner support
[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         return m_frontend->get().tune(*feparm);
495 }
496
497 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
498 {
499         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
500         return 0;
501 }
502
503 RESULT eDVBChannel::getState(int &state)
504 {
505         state = m_state;
506         return 0;
507 }
508
509 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
510 {
511         return -1;
512 }
513
514 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
515 {
516         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
517         
518         if (!our_demux)
519         {
520                 demux = 0;
521                 
522                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
523                         return 0;
524         }
525         
526         demux = *our_demux;
527         return 0;
528 }
529
530 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
531 {
532         frontend = &m_frontend->get();
533         if (frontend)
534                 return 0;
535         else
536                 return -ENODEV;
537 }
538
539 RESULT eDVBChannel::playFile(const char *file)
540 {
541         ASSERT(!m_frontend);
542         if (m_pvr_thread)
543         {
544                 m_pvr_thread->stop();
545                 delete m_pvr_thread;
546                 m_pvr_thread = 0;
547         }
548         
549         m_tstools.openFile(file);
550         
551                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
552                    THEN DO A REAL FIX HERE! */
553         
554                 /* (this codepath needs to be improved anyway.) */
555         m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
556         if (m_pvr_fd_dst < 0)
557         {
558                 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
559                 return -ENODEV;
560         }
561         
562         m_pvr_fd_src = open(file, O_RDONLY);
563         if (m_pvr_fd_src < 0)
564         {
565                 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
566                 close(m_pvr_fd_dst);
567                 return -ENOENT;
568         }
569         
570         m_state = state_ok;
571         m_stateChanged(this);
572         
573         m_pvr_thread = new eFilePushThread();
574         m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
575
576         return 0;
577 }
578
579 RESULT eDVBChannel::getLength(pts_t &len)
580 {
581         return m_tstools.calcLen(len);
582 }
583
584 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
585 {
586         if (!m_decoder_demux)
587                 return -1;
588         
589         off_t begin = 0;
590                 /* getPTS for offset 0 is cached, so it doesn't harm. */
591         int r = m_tstools.getPTS(begin, pos);
592         if (r)
593         {
594                 eDebug("tstools getpts(0) failed!");
595                 return r;
596         }
597         
598         pts_t now;
599         
600         r = m_decoder_demux->get().getSTC(now);
601
602         if (r)
603         {
604                 eDebug("demux getSTC failed");
605                 return -1;
606         }
607         
608 //      eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
609                 /* when we are less than 10 seconds before the start, return 0. */
610                 /* (we're just waiting for the timespam to start) */
611         if ((now < pos) && ((pos - now) < 90000 * 10))
612         {
613                 pos = 0;
614                 return 0;
615         }
616         
617         if (now < pos) /* wrap around */
618                 pos = now + ((pts_t)1)<<33 - pos;
619         else
620                 pos = now - pos;
621         
622         return 0;
623 }
624
625 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
626 {
627         int bitrate = m_tstools.calcBitrate(); /* in bits/s */
628         
629         if (bitrate == -1)
630                 return -1;
631         
632         if (relative)
633         {
634                 pts_t now;
635                 if (getCurrentPosition(now))
636                 {
637                         eDebug("seekTo: getCurrentPosition failed!");
638                         return -1;
639                 }
640                 pts += now;
641         }
642         
643         if (pts < 0)
644                 pts = 0;
645         
646         off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
647         
648         seekToPosition(offset);
649         return 0;
650 }
651
652 RESULT eDVBChannel::seekToPosition(const off_t &r)
653 {
654                         /* when seeking, we have to ensure that all buffers are flushed.
655                            there are basically 3 buffers:
656                            a.) the filepush's internal buffer
657                            b.) the PVR buffer (before demux)
658                            c.) the ratebuffer (after demux)
659                            
660                            it's important to clear them in the correct order, otherwise
661                            the ratebuffer (for example) would immediately refill from
662                            the not-yet-flushed PVR buffer.
663                         */
664         eDebug("eDVBChannel: seekToPosition .. %llx", r);
665         m_pvr_thread->pause();
666
667                 /* flush internal filepush buffer */
668         m_pvr_thread->flush();
669
670                 /* HACK: flush PVR buffer */
671         ::ioctl(m_pvr_fd_dst, 0);
672         
673                 /* flush ratebuffers (video, audio) */
674         if (m_decoder_demux)
675                 m_decoder_demux->get().flush();
676
677                 /* demux will also flush all decoder.. */
678         m_pvr_thread->seek(SEEK_SET, r);
679         m_pvr_thread->resume();
680         return 0;
681 }