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;
200 if (!adapter->getFrontend(frontend, i))
201 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
205 RESULT eDVBResourceManager::allocateFrontend(const eDVBChannelID &chid, ePtr<eDVBAllocatedFrontend> &fe)
207 /* find first unused frontend. we ignore compatibility for now. */
208 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
211 fe = new eDVBAllocatedFrontend(i);
217 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
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. */
222 eDebug("allocate demux");
223 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
225 if (i == m_demux.end())
229 /* FIXME: hardware demux policy */
230 if (!(cap & iDVBChannel::capDecode))
233 for (; i != m_demux.end(); ++i, ++n)
234 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
236 if ((cap & iDVBChannel::capDecode) && n)
239 demux = new eDVBAllocatedDemux(i);
241 demux->get().setSourceFrontend(fe->m_frontend->getID());
243 demux->get().setSourcePVR(0);
244 eDebug("demux (%d) found (fe id: %d)", n, fe->m_frontend->getID());
247 eDebug("demux not found");
251 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
257 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
267 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
269 /* first, check if a channel is already existing. */
271 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
272 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
274 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
275 if (i->m_channel_id == channelid)
277 // eDebug("found shared channel..");
278 channel = i->m_channel;
283 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
285 /* allocate a frontend. */
287 ePtr<eDVBAllocatedFrontend> fe;
289 if (allocateFrontend(channelid, fe))
290 return errNoFrontend;
292 // will be allocated on demand:
293 // ePtr<eDVBAllocatedDemux> demux;
295 // if (allocateDemux(*fe, demux))
296 // return errNoDemux;
299 ePtr<eDVBChannel> ch;
300 ch = new eDVBChannel(this, fe);
302 ePtr<iDVBFrontend> myfe;
303 if (!ch->getFrontend(myfe))
306 res = ch->setChannel(channelid);
310 return errChidNotFound;
317 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
319 ePtr<eDVBAllocatedFrontend> fe;
321 if (allocateFrontend(eDVBChannelID(), fe))
322 return errNoFrontend;
324 // ePtr<eDVBAllocatedDemux> demux;
326 // if (allocateDemux(*fe, demux))
327 // return errNoDemux;
330 ch = new eDVBChannel(this, fe);
332 ePtr<iDVBFrontend> myfe;
333 if (!ch->getFrontend(myfe))
341 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
343 ePtr<eDVBAllocatedDemux> demux;
345 // if (allocateDemux(0, demux))
346 // return errNoDemux;
349 ch = new eDVBChannel(this, 0);
355 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
357 m_active_channels.push_back(active_channel(chid, ch));
358 // /* emit */ m_channelAdded(ch);
362 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
365 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
367 if (i->m_channel == ch)
369 i = m_active_channels.erase(i);
380 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
382 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
386 DEFINE_REF(eDVBChannel);
388 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
390 m_frontend = frontend;
395 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
398 eDVBChannel::~eDVBChannel()
401 m_mgr->removeChannel(this);
405 m_pvr_thread->stop();
406 ::close(m_pvr_fd_src);
407 ::close(m_pvr_fd_dst);
412 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
414 int state, ourstate = 0;
416 /* if we are already in shutdown, don't change state. */
417 if (m_state == state_release)
420 if (fe->getState(state))
423 if (state == iDVBFrontend::stateLock)
425 eDebug("OURSTATE: ok");
427 } else if (state == iDVBFrontend::stateTuning)
429 eDebug("OURSTATE: tuning");
430 ourstate = state_tuning;
431 } else if (state == iDVBFrontend::stateLostLock)
433 eDebug("OURSTATE: lost lock");
434 ourstate = state_unavailable;
435 } else if (state == iDVBFrontend::stateFailed)
437 eDebug("OURSTATE: failed");
438 ourstate = state_failed;
440 eFatal("state unknown");
442 if (ourstate != m_state)
445 m_stateChanged(this);
449 void eDVBChannel::AddUse()
454 void eDVBChannel::ReleaseUse()
458 m_state = state_release;
459 m_stateChanged(this);
463 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
466 m_mgr->removeChannel(this);
471 ePtr<iDVBChannelList> list;
473 if (m_mgr->getChannelList(list))
475 eDebug("no channel list set!");
479 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
480 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
482 ePtr<iDVBFrontendParameters> feparm;
483 if (list->getChannelFrontendData(channelid, feparm))
485 eDebug("channel not found!");
491 eDebug("no frontend to tune!");
495 m_channel_id = channelid;
496 m_mgr->addChannel(channelid, this);
497 m_state = state_tuning;
498 /* if tuning fails, shutdown the channel immediately. */
500 res = m_frontend->get().tune(*feparm);
504 m_state = state_release;
505 m_stateChanged(this);
512 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
514 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
518 RESULT eDVBChannel::getState(int &state)
524 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
529 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
531 eDebug("get %d demux", cap);
532 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
538 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
551 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
553 frontend = &m_frontend->get();
560 RESULT eDVBChannel::playFile(const char *file)
565 m_pvr_thread->stop();
570 m_tstools.openFile(file);
572 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
573 THEN DO A REAL FIX HERE! */
575 /* (this codepath needs to be improved anyway.) */
576 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
577 if (m_pvr_fd_dst < 0)
579 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
583 m_pvr_fd_src = open(file, O_RDONLY);
584 if (m_pvr_fd_src < 0)
586 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
592 m_stateChanged(this);
594 m_pvr_thread = new eFilePushThread();
595 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
600 RESULT eDVBChannel::getLength(pts_t &len)
602 return m_tstools.calcLen(len);
605 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
607 if (!m_decoder_demux)
611 /* getPTS for offset 0 is cached, so it doesn't harm. */
612 int r = m_tstools.getPTS(begin, pos);
615 eDebug("tstools getpts(0) failed!");
621 r = m_decoder_demux->get().getSTC(now);
625 eDebug("demux getSTC failed");
629 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
630 /* when we are less than 10 seconds before the start, return 0. */
631 /* (we're just waiting for the timespam to start) */
632 if ((now < pos) && ((pos - now) < 90000 * 10))
638 if (now < pos) /* wrap around */
639 pos = now + ((pts_t)1)<<33 - pos;
646 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
648 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
656 if (getCurrentPosition(now))
658 eDebug("seekTo: getCurrentPosition failed!");
667 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
669 seekToPosition(offset);
673 RESULT eDVBChannel::seekToPosition(const off_t &r)
675 /* when seeking, we have to ensure that all buffers are flushed.
676 there are basically 3 buffers:
677 a.) the filepush's internal buffer
678 b.) the PVR buffer (before demux)
679 c.) the ratebuffer (after demux)
681 it's important to clear them in the correct order, otherwise
682 the ratebuffer (for example) would immediately refill from
683 the not-yet-flushed PVR buffer.
685 eDebug("eDVBChannel: seekToPosition .. %llx", r);
686 m_pvr_thread->pause();
688 /* flush internal filepush buffer */
689 m_pvr_thread->flush();
691 /* HACK: flush PVR buffer */
692 ::ioctl(m_pvr_fd_dst, 0);
694 /* flush ratebuffers (video, audio) */
696 m_decoder_demux->get().flush();
698 /* demux will also flush all decoder.. */
699 m_pvr_thread->seek(SEEK_SET, r);
700 m_pvr_thread->resume();