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);
236 eDebug("demux found");
239 eDebug("demux not found");
243 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
249 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
259 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
261 /* first, check if a channel is already existing. */
263 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
264 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
266 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
267 if (i->m_channel_id == channelid)
269 // eDebug("found shared channel..");
270 channel = i->m_channel;
275 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
277 /* allocate a frontend. */
279 ePtr<eDVBAllocatedFrontend> fe;
281 if (allocateFrontend(channelid, fe))
282 return errNoFrontend;
284 // will be allocated on demand:
285 // ePtr<eDVBAllocatedDemux> demux;
287 // if (allocateDemux(*fe, demux))
288 // return errNoDemux;
291 ePtr<eDVBChannel> ch;
292 ch = new eDVBChannel(this, fe);
294 ePtr<iDVBFrontend> myfe;
295 if (!ch->getFrontend(myfe))
298 res = ch->setChannel(channelid);
302 return errChidNotFound;
309 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
311 ePtr<eDVBAllocatedFrontend> fe;
313 if (allocateFrontend(eDVBChannelID(), fe))
314 return errNoFrontend;
316 // ePtr<eDVBAllocatedDemux> demux;
318 // if (allocateDemux(*fe, demux))
319 // return errNoDemux;
322 ch = new eDVBChannel(this, fe);
324 ePtr<iDVBFrontend> myfe;
325 if (!ch->getFrontend(myfe))
333 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
335 ePtr<eDVBAllocatedDemux> demux;
337 // if (allocateDemux(0, demux))
338 // return errNoDemux;
341 ch = new eDVBChannel(this, 0);
347 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
349 m_active_channels.push_back(active_channel(chid, ch));
350 /* emit */ m_channelAdded(ch);
354 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
357 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
359 if (i->m_channel == ch)
361 i = m_active_channels.erase(i);
372 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
374 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
378 DEFINE_REF(eDVBChannel);
380 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
382 m_frontend = frontend;
387 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
390 eDVBChannel::~eDVBChannel()
393 m_mgr->removeChannel(this);
397 m_pvr_thread->stop();
398 ::close(m_pvr_fd_src);
399 ::close(m_pvr_fd_dst);
404 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
406 int state, ourstate = 0;
408 /* if we are already in shutdown, don't change state. */
409 if (m_state == state_release)
412 if (fe->getState(state))
415 if (state == iDVBFrontend::stateLock)
417 eDebug("OURSTATE: ok");
419 } else if (state == iDVBFrontend::stateTuning)
421 eDebug("OURSTATE: tuning");
422 ourstate = state_tuning;
423 } else if (state == iDVBFrontend::stateLostLock)
425 eDebug("OURSTATE: lost lock");
426 ourstate = state_unavailable;
427 } else if (state == iDVBFrontend::stateFailed)
429 eDebug("OURSTATE: failed");
430 ourstate = state_failed;
432 eFatal("state unknown");
434 if (ourstate != m_state)
437 m_stateChanged(this);
441 void eDVBChannel::AddUse()
446 void eDVBChannel::ReleaseUse()
450 m_state = state_release;
451 m_stateChanged(this);
455 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
458 m_mgr->removeChannel(this);
463 ePtr<iDVBChannelList> list;
465 if (m_mgr->getChannelList(list))
467 eDebug("no channel list set!");
471 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
472 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
474 ePtr<iDVBFrontendParameters> feparm;
475 if (list->getChannelFrontendData(channelid, feparm))
477 eDebug("channel not found!");
483 eDebug("no frontend to tune!");
487 m_channel_id = channelid;
488 m_mgr->addChannel(channelid, this);
489 m_state = state_tuning;
490 return m_frontend->get().tune(*feparm);
493 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
495 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
499 RESULT eDVBChannel::getState(int &state)
505 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
510 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
512 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
518 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
526 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
528 frontend = &m_frontend->get();
535 RESULT eDVBChannel::playFile(const char *file)
540 m_pvr_thread->stop();
545 m_tstools.openFile(file);
547 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
548 THEN DO A REAL FIX HERE! */
550 /* (this codepath needs to be improved anyway.) */
551 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
552 if (m_pvr_fd_dst < 0)
554 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
558 m_pvr_fd_src = open(file, O_RDONLY);
559 if (m_pvr_fd_src < 0)
561 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
567 m_stateChanged(this);
569 m_pvr_thread = new eFilePushThread();
570 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
575 RESULT eDVBChannel::getLength(pts_t &len)
577 return m_tstools.calcLen(len);
580 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
582 if (!m_decoder_demux)
586 /* getPTS for offset 0 is cached, so it doesn't harm. */
587 int r = m_tstools.getPTS(begin, pos);
590 eDebug("tstools getpts(0) failed!");
596 r = m_decoder_demux->get().getSTC(now);
600 eDebug("demux getSTC failed");
604 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
605 /* when we are less than 10 seconds before the start, return 0. */
606 /* (we're just waiting for the timespam to start) */
607 if ((now < pos) && ((pos - now) < 90000 * 10))
613 if (now < pos) /* wrap around */
614 pos = now + ((pts_t)1)<<33 - pos;
621 RESULT eDVBChannel::seekTo(pts_t &pts)
624 eDebug("eDVBChannel: seekTo .. %llx", pts);
625 m_pvr_thread->pause();
627 m_decoder_demux->get().flush();
628 /* demux will also flush all decoder.. */
632 if (!m_tstools.getPosition(pts, r));
633 m_pvr_thread->seek(r);
635 eDebug("getPosition failed!");
636 m_pvr_thread->resume();
640 RESULT eDVBChannel::seekToPosition(int relative, const off_t &r)
642 /* when seeking, we have to ensure that all buffers are flushed.
643 there are basically 3 buffers:
644 a.) the filepush's internal buffer
645 b.) the PVR buffer (before demux)
646 c.) the ratebuffer (after demux)
648 it's important to clear them in the correct order, otherwise
649 the ratebuffer (for example) would immediately refill from
650 the not-yet-flushed PVR buffer.
652 eDebug("eDVBChannel: seekToPosition .. %llx", r);
653 m_pvr_thread->pause();
655 /* flush internal filepush buffer */
656 m_pvr_thread->flush();
658 /* HACK: flush PVR buffer */
659 ::ioctl(m_pvr_fd_dst, 0);
661 /* flush ratebuffers (video, audio) */
663 m_decoder_demux->get().flush();
665 /* demux will also flush all decoder.. */
666 m_pvr_thread->seek(relative ? SEEK_CUR : SEEK_SET, r);
667 m_pvr_thread->resume();