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