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())
228 /* FIXME: hardware demux policy */
229 if (!(cap & iDVBChannel::capDecode))
232 for (; i != m_demux.end(); ++i)
233 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
235 demux = new eDVBAllocatedDemux(i);
237 demux->get().setSourceFrontend(fe->m_frontend->getID());
239 demux->get().setSourcePVR(0);
240 eDebug("demux found");
243 eDebug("demux not found");
247 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
253 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
263 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
265 /* first, check if a channel is already existing. */
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)
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)
273 // eDebug("found shared channel..");
274 channel = i->m_channel;
279 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
281 /* allocate a frontend. */
283 ePtr<eDVBAllocatedFrontend> fe;
285 if (allocateFrontend(channelid, fe))
286 return errNoFrontend;
288 // will be allocated on demand:
289 // ePtr<eDVBAllocatedDemux> demux;
291 // if (allocateDemux(*fe, demux))
292 // return errNoDemux;
295 ePtr<eDVBChannel> ch;
296 ch = new eDVBChannel(this, fe);
298 ePtr<iDVBFrontend> myfe;
299 if (!ch->getFrontend(myfe))
302 res = ch->setChannel(channelid);
306 return errChidNotFound;
313 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
315 ePtr<eDVBAllocatedFrontend> fe;
317 if (allocateFrontend(eDVBChannelID(), fe))
318 return errNoFrontend;
320 // ePtr<eDVBAllocatedDemux> demux;
322 // if (allocateDemux(*fe, demux))
323 // return errNoDemux;
326 ch = new eDVBChannel(this, fe);
328 ePtr<iDVBFrontend> myfe;
329 if (!ch->getFrontend(myfe))
337 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
339 ePtr<eDVBAllocatedDemux> demux;
341 // if (allocateDemux(0, demux))
342 // return errNoDemux;
345 ch = new eDVBChannel(this, 0);
351 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
353 m_active_channels.push_back(active_channel(chid, ch));
354 /* emit */ m_channelAdded(ch);
358 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
361 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
363 if (i->m_channel == ch)
365 i = m_active_channels.erase(i);
376 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
378 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
382 DEFINE_REF(eDVBChannel);
384 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
386 m_frontend = frontend;
391 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
394 eDVBChannel::~eDVBChannel()
397 m_mgr->removeChannel(this);
401 m_pvr_thread->stop();
402 ::close(m_pvr_fd_src);
403 ::close(m_pvr_fd_dst);
408 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
410 int state, ourstate = 0;
412 /* if we are already in shutdown, don't change state. */
413 if (m_state == state_release)
416 if (fe->getState(state))
419 if (state == iDVBFrontend::stateLock)
421 eDebug("OURSTATE: ok");
423 } else if (state == iDVBFrontend::stateTuning)
425 eDebug("OURSTATE: tuning");
426 ourstate = state_tuning;
427 } else if (state == iDVBFrontend::stateLostLock)
429 eDebug("OURSTATE: lost lock");
430 ourstate = state_unavailable;
431 } else if (state == iDVBFrontend::stateFailed)
433 eDebug("OURSTATE: failed");
434 ourstate = state_failed;
436 eFatal("state unknown");
438 if (ourstate != m_state)
441 m_stateChanged(this);
445 void eDVBChannel::AddUse()
450 void eDVBChannel::ReleaseUse()
454 m_state = state_release;
455 m_stateChanged(this);
459 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
462 m_mgr->removeChannel(this);
467 ePtr<iDVBChannelList> list;
469 if (m_mgr->getChannelList(list))
471 eDebug("no channel list set!");
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());
478 ePtr<iDVBFrontendParameters> feparm;
479 if (list->getChannelFrontendData(channelid, feparm))
481 eDebug("channel not found!");
487 eDebug("no frontend to tune!");
491 m_channel_id = channelid;
492 m_mgr->addChannel(channelid, this);
493 m_state = state_tuning;
494 /* if tuning fails, shutdown the channel immediately. */
496 res = m_frontend->get().tune(*feparm);
500 m_state = state_release;
501 m_stateChanged(this);
508 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
510 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
514 RESULT eDVBChannel::getState(int &state)
520 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
525 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
527 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
533 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
541 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
543 frontend = &m_frontend->get();
550 RESULT eDVBChannel::playFile(const char *file)
555 m_pvr_thread->stop();
560 m_tstools.openFile(file);
562 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
563 THEN DO A REAL FIX HERE! */
565 /* (this codepath needs to be improved anyway.) */
566 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
567 if (m_pvr_fd_dst < 0)
569 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
573 m_pvr_fd_src = open(file, O_RDONLY);
574 if (m_pvr_fd_src < 0)
576 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
582 m_stateChanged(this);
584 m_pvr_thread = new eFilePushThread();
585 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
590 RESULT eDVBChannel::getLength(pts_t &len)
592 return m_tstools.calcLen(len);
595 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
597 if (!m_decoder_demux)
601 /* getPTS for offset 0 is cached, so it doesn't harm. */
602 int r = m_tstools.getPTS(begin, pos);
605 eDebug("tstools getpts(0) failed!");
611 r = m_decoder_demux->get().getSTC(now);
615 eDebug("demux getSTC failed");
619 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
620 /* when we are less than 10 seconds before the start, return 0. */
621 /* (we're just waiting for the timespam to start) */
622 if ((now < pos) && ((pos - now) < 90000 * 10))
628 if (now < pos) /* wrap around */
629 pos = now + ((pts_t)1)<<33 - pos;
636 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
638 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
646 if (getCurrentPosition(now))
648 eDebug("seekTo: getCurrentPosition failed!");
657 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
659 seekToPosition(offset);
663 RESULT eDVBChannel::seekToPosition(const off_t &r)
665 /* when seeking, we have to ensure that all buffers are flushed.
666 there are basically 3 buffers:
667 a.) the filepush's internal buffer
668 b.) the PVR buffer (before demux)
669 c.) the ratebuffer (after demux)
671 it's important to clear them in the correct order, otherwise
672 the ratebuffer (for example) would immediately refill from
673 the not-yet-flushed PVR buffer.
675 eDebug("eDVBChannel: seekToPosition .. %llx", r);
676 m_pvr_thread->pause();
678 /* flush internal filepush buffer */
679 m_pvr_thread->flush();
681 /* HACK: flush PVR buffer */
682 ::ioctl(m_pvr_fd_dst, 0);
684 /* flush ratebuffers (video, audio) */
686 m_decoder_demux->get().flush();
688 /* demux will also flush all decoder.. */
689 m_pvr_thread->seek(SEEK_SET, r);
690 m_pvr_thread->resume();