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 return m_frontend->get().tune(*feparm);
497 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
499 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
503 RESULT eDVBChannel::getState(int &state)
509 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
514 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
516 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
522 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
530 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
532 frontend = &m_frontend->get();
539 RESULT eDVBChannel::playFile(const char *file)
544 m_pvr_thread->stop();
549 m_tstools.openFile(file);
551 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
552 THEN DO A REAL FIX HERE! */
554 /* (this codepath needs to be improved anyway.) */
555 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
556 if (m_pvr_fd_dst < 0)
558 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
562 m_pvr_fd_src = open(file, O_RDONLY);
563 if (m_pvr_fd_src < 0)
565 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
571 m_stateChanged(this);
573 m_pvr_thread = new eFilePushThread();
574 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
579 RESULT eDVBChannel::getLength(pts_t &len)
581 return m_tstools.calcLen(len);
584 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
586 if (!m_decoder_demux)
590 /* getPTS for offset 0 is cached, so it doesn't harm. */
591 int r = m_tstools.getPTS(begin, pos);
594 eDebug("tstools getpts(0) failed!");
600 r = m_decoder_demux->get().getSTC(now);
604 eDebug("demux getSTC failed");
608 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
609 /* when we are less than 10 seconds before the start, return 0. */
610 /* (we're just waiting for the timespam to start) */
611 if ((now < pos) && ((pos - now) < 90000 * 10))
617 if (now < pos) /* wrap around */
618 pos = now + ((pts_t)1)<<33 - pos;
625 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
627 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
635 if (getCurrentPosition(now))
637 eDebug("seekTo: getCurrentPosition failed!");
646 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
648 seekToPosition(offset);
652 RESULT eDVBChannel::seekToPosition(const off_t &r)
654 /* when seeking, we have to ensure that all buffers are flushed.
655 there are basically 3 buffers:
656 a.) the filepush's internal buffer
657 b.) the PVR buffer (before demux)
658 c.) the ratebuffer (after demux)
660 it's important to clear them in the correct order, otherwise
661 the ratebuffer (for example) would immediately refill from
662 the not-yet-flushed PVR buffer.
664 eDebug("eDVBChannel: seekToPosition .. %llx", r);
665 m_pvr_thread->pause();
667 /* flush internal filepush buffer */
668 m_pvr_thread->flush();
670 /* HACK: flush PVR buffer */
671 ::ioctl(m_pvr_fd_dst, 0);
673 /* flush ratebuffers (video, audio) */
675 m_decoder_demux->get().flush();
677 /* demux will also flush all decoder.. */
678 m_pvr_thread->seek(SEEK_SET, r);
679 m_pvr_thread->resume();