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>
12 #include <sys/ioctl.h>
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
17 DEFINE_REF(eDVBAllocatedFrontend);
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
29 DEFINE_REF(eDVBAllocatedDemux);
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
41 DEFINE_REF(eDVBResourceManager);
43 eDVBResourceManager *eDVBResourceManager::instance;
45 eDVBResourceManager::eDVBResourceManager()
49 m_sec = new eDVBSatelliteEquipmentControl;
53 /* search available adapters... */
58 while (eDVBAdapterLinux::exist(num_adapter))
60 addAdapter(new eDVBAdapterLinux(num_adapter));
64 eDebug("found %d adapter, %d frontends and %d demux",
65 m_adapter.size(), m_frontend.size(), m_demux.size());
69 DEFINE_REF(eDVBAdapterLinux);
70 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
75 eDebug("scanning for frontends..");
80 #if HAVE_DVB_API_VERSION < 3
81 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
83 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
85 if (stat(filename, &s))
87 ePtr<eDVBFrontend> fe;
90 fe = new eDVBFrontend(m_nr, num_fe, ok);
92 m_frontend.push_back(fe);
102 #if HAVE_DVB_API_VERSION < 3
103 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
105 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
107 if (stat(filename, &s))
109 ePtr<eDVBDemux> demux;
111 demux = new eDVBDemux(m_nr, num_demux);
112 m_demux.push_back(demux);
118 int eDVBAdapterLinux::getNumDemux()
120 return m_demux.size();
123 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
125 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
126 while (nr && (i != m_demux.end()))
132 if (i != m_demux.end())
140 int eDVBAdapterLinux::getNumFrontends()
142 return m_frontend.size();
145 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
147 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
148 while (nr && (i != m_frontend.end()))
154 if (i != m_frontend.end())
162 int eDVBAdapterLinux::exist(int nr)
166 #if HAVE_DVB_API_VERSION < 3
167 sprintf(filename, "/dev/dvb/card%d", nr);
169 sprintf(filename, "/dev/dvb/adapter%d", nr);
171 if (!stat(filename, &s))
176 eDVBResourceManager::~eDVBResourceManager()
178 if (instance == this)
182 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
184 int num_fe = adapter->getNumFrontends();
185 int num_demux = adapter->getNumDemux();
187 m_adapter.push_back(adapter);
190 for (i=0; i<num_demux; ++i)
192 ePtr<eDVBDemux> demux;
193 if (!adapter->getDemux(demux, i))
194 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
197 for (i=0; i<num_fe; ++i)
199 ePtr<eDVBFrontend> frontend;
201 if (!adapter->getFrontend(frontend, i))
203 frontend->setSEC(m_sec);
204 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
209 RESULT eDVBResourceManager::allocateFrontend(ePtr<iDVBFrontendParameters> &feparm, ePtr<eDVBAllocatedFrontend> &fe)
211 ePtr<eDVBRegisteredFrontend> best;
214 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
217 int c = i->m_frontend->isCompatibleWith(feparm);
227 fe = new eDVBAllocatedFrontend(best);
236 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
238 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
239 never use the first one unless we need a decoding demux. */
241 eDebug("allocate demux");
242 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
244 if (i == m_demux.end())
248 /* FIXME: hardware demux policy */
249 if (!(cap & iDVBChannel::capDecode))
252 for (; i != m_demux.end(); ++i, ++n)
253 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
255 if ((cap & iDVBChannel::capDecode) && n)
258 demux = new eDVBAllocatedDemux(i);
260 demux->get().setSourceFrontend(fe->m_frontend->getID());
262 demux->get().setSourcePVR(0);
265 eDebug("demux not found");
269 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
275 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
285 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
287 /* first, check if a channel is already existing. */
289 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
290 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
292 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
293 if (i->m_channel_id == channelid)
295 // eDebug("found shared channel..");
296 channel = i->m_channel;
301 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
305 eDebug("no channel list set!");
309 ePtr<iDVBFrontendParameters> feparm;
310 if (m_list->getChannelFrontendData(channelid, feparm))
312 eDebug("channel not found!");
316 /* allocate a frontend. */
318 ePtr<eDVBAllocatedFrontend> fe;
320 if (allocateFrontend(feparm, fe))
321 return errNoFrontend;
323 // will be allocated on demand:
324 // ePtr<eDVBAllocatedDemux> demux;
326 // if (allocateDemux(*fe, demux))
327 // return errNoDemux;
330 ePtr<eDVBChannel> ch;
331 ch = new eDVBChannel(this, fe);
333 res = ch->setChannel(channelid, feparm);
337 return errChidNotFound;
344 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
346 ePtr<eDVBAllocatedFrontend> fe;
348 #warning FIXME allocateRawChannel
350 // if (allocateFrontend(eDVBChannelID(), fe))
351 return errNoFrontend;
353 // ePtr<eDVBAllocatedDemux> demux;
355 // if (allocateDemux(*fe, demux))
356 // return errNoDemux;
359 ch = new eDVBChannel(this, fe);
366 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
368 ePtr<eDVBAllocatedDemux> demux;
370 // if (allocateDemux(0, demux))
371 // return errNoDemux;
374 ch = new eDVBChannel(this, 0);
380 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
382 m_active_channels.push_back(active_channel(chid, ch));
383 /* emit */ m_channelAdded(ch);
387 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
390 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
392 if (i->m_channel == ch)
394 i = m_active_channels.erase(i);
405 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
407 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
411 DEFINE_REF(eDVBChannel);
413 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
415 m_frontend = frontend;
420 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
423 eDVBChannel::~eDVBChannel()
426 m_mgr->removeChannel(this);
430 m_pvr_thread->stop();
431 ::close(m_pvr_fd_src);
432 ::close(m_pvr_fd_dst);
437 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
439 int state, ourstate = 0;
441 /* if we are already in shutdown, don't change state. */
442 if (m_state == state_release)
445 if (fe->getState(state))
448 if (state == iDVBFrontend::stateLock)
450 eDebug("OURSTATE: ok");
452 } else if (state == iDVBFrontend::stateTuning)
454 eDebug("OURSTATE: tuning");
455 ourstate = state_tuning;
456 } else if (state == iDVBFrontend::stateLostLock)
458 eDebug("OURSTATE: lost lock");
459 ourstate = state_unavailable;
460 } else if (state == iDVBFrontend::stateFailed)
462 eDebug("OURSTATE: failed");
463 ourstate = state_failed;
465 eFatal("state unknown");
467 if (ourstate != m_state)
470 m_stateChanged(this);
474 void eDVBChannel::AddUse()
479 void eDVBChannel::ReleaseUse()
483 m_state = state_release;
484 m_stateChanged(this);
488 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
491 m_mgr->removeChannel(this);
498 eDebug("no frontend to tune!");
502 m_channel_id = channelid;
503 m_mgr->addChannel(channelid, this);
504 m_state = state_tuning;
505 /* if tuning fails, shutdown the channel immediately. */
507 res = m_frontend->get().tune(*feparm);
511 m_state = state_release;
512 m_stateChanged(this);
519 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
521 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
525 RESULT eDVBChannel::getState(int &state)
531 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
536 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
538 eDebug("get %d demux", cap);
539 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
545 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
558 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
560 frontend = &m_frontend->get();
567 RESULT eDVBChannel::playFile(const char *file)
572 m_pvr_thread->stop();
577 m_tstools.openFile(file);
579 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
580 THEN DO A REAL FIX HERE! */
582 /* (this codepath needs to be improved anyway.) */
583 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
584 if (m_pvr_fd_dst < 0)
586 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
590 m_pvr_fd_src = open(file, O_RDONLY);
591 if (m_pvr_fd_src < 0)
593 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
599 m_stateChanged(this);
601 m_pvr_thread = new eFilePushThread();
602 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
607 RESULT eDVBChannel::getLength(pts_t &len)
609 return m_tstools.calcLen(len);
612 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos)
618 /* getPTS for offset 0 is cached, so it doesn't harm. */
619 int r = m_tstools.getPTS(begin, pos);
622 eDebug("tstools getpts(0) failed!");
628 r = decoding_demux->getSTC(now);
632 eDebug("demux getSTC failed");
636 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
637 /* when we are less than 10 seconds before the start, return 0. */
638 /* (we're just waiting for the timespam to start) */
639 if ((now < pos) && ((pos - now) < 90000 * 10))
645 if (now < pos) /* wrap around */
646 pos = now + ((pts_t)1)<<33 - pos;
653 RESULT eDVBChannel::seekTo(iDVBDemux *decoding_demux, int relative, pts_t &pts)
655 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
663 if (getCurrentPosition(decoding_demux, now))
665 eDebug("seekTo: getCurrentPosition failed!");
674 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
676 seekToPosition(decoding_demux, offset);
680 RESULT eDVBChannel::seekToPosition(iDVBDemux *decoding_demux, const off_t &r)
682 /* when seeking, we have to ensure that all buffers are flushed.
683 there are basically 3 buffers:
684 a.) the filepush's internal buffer
685 b.) the PVR buffer (before demux)
686 c.) the ratebuffer (after demux)
688 it's important to clear them in the correct order, otherwise
689 the ratebuffer (for example) would immediately refill from
690 the not-yet-flushed PVR buffer.
692 eDebug("eDVBChannel: seekToPosition .. %llx", r);
693 m_pvr_thread->pause();
695 /* flush internal filepush buffer */
696 m_pvr_thread->flush();
698 /* HACK: flush PVR buffer */
699 ::ioctl(m_pvr_fd_dst, 0);
701 /* flush ratebuffers (video, audio) */
703 decoding_demux->flush();
705 /* demux will also flush all decoder.. */
706 m_pvr_thread->seek(SEEK_SET, r);
707 m_pvr_thread->resume();