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