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 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
55 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
57 ePtr<eDVBResourceManager> ptr;
58 eDVBResourceManager::getInstance(ptr);
62 eDVBResourceManager::eDVBResourceManager()
63 :m_releaseCachedChannelTimer(eApp)
67 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
71 /* search available adapters... */
76 while (eDVBAdapterLinux::exist(num_adapter))
78 addAdapter(new eDVBAdapterLinux(num_adapter));
82 eDebug("found %d adapter, %d frontends and %d demux",
83 m_adapter.size(), m_frontend.size(), m_demux.size());
85 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
88 void eDVBResourceManager::feStateChanged()
91 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
93 mask |= ( 1 << i->m_frontend->getID() );
94 /* emit */ frontendUseMaskChanged(mask);
97 DEFINE_REF(eDVBAdapterLinux);
98 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
103 eDebug("scanning for frontends..");
108 #if HAVE_DVB_API_VERSION < 3
109 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
111 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
113 if (stat(filename, &s))
115 ePtr<eDVBFrontend> fe;
118 fe = new eDVBFrontend(m_nr, num_fe, ok);
120 m_frontend.push_back(fe);
130 #if HAVE_DVB_API_VERSION < 3
131 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
133 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
135 if (stat(filename, &s))
137 ePtr<eDVBDemux> demux;
139 demux = new eDVBDemux(m_nr, num_demux);
140 m_demux.push_back(demux);
146 int eDVBAdapterLinux::getNumDemux()
148 return m_demux.size();
151 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
153 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
154 while (nr && (i != m_demux.end()))
160 if (i != m_demux.end())
168 int eDVBAdapterLinux::getNumFrontends()
170 return m_frontend.size();
173 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
175 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
176 while (nr && (i != m_frontend.end()))
182 if (i != m_frontend.end())
190 int eDVBAdapterLinux::exist(int nr)
194 #if HAVE_DVB_API_VERSION < 3
195 sprintf(filename, "/dev/dvb/card%d", nr);
197 sprintf(filename, "/dev/dvb/adapter%d", nr);
199 if (!stat(filename, &s))
204 eDVBResourceManager::~eDVBResourceManager()
206 if (instance == this)
210 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
212 int num_fe = adapter->getNumFrontends();
213 int num_demux = adapter->getNumDemux();
215 m_adapter.push_back(adapter);
218 for (i=0; i<num_demux; ++i)
220 ePtr<eDVBDemux> demux;
221 if (!adapter->getDemux(demux, i))
222 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
225 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
226 for (i=0; i<num_fe; ++i)
228 ePtr<eDVBFrontend> frontend;
229 if (!adapter->getFrontend(frontend, i))
232 frontend->getFrontendType(frontendType);
233 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
234 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
235 m_frontend.push_back(new_fe);
236 frontend->setSEC(m_sec);
237 // we must link all dvb-t frontends ( for active antenna voltage )
238 if (frontendType == iDVBFrontend::feTerrestrial)
240 if (prev_dvbt_frontend)
242 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)new_fe);
243 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*prev_dvbt_frontend));
245 prev_dvbt_frontend = new_fe;
251 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
253 ePtr<eDVBRegisteredFrontend> best;
256 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
259 int c = i->m_frontend->isCompatibleWith(feparm);
269 fe = new eDVBAllocatedFrontend(best);
278 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
280 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
281 if ((!nr) && !i->m_inuse)
283 fe = new eDVBAllocatedFrontend(i);
291 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
293 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
294 never use the first one unless we need a decoding demux. */
296 eDebug("allocate demux");
297 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
299 if (i == m_demux.end())
303 /* FIXME: hardware demux policy */
304 if (!(cap & iDVBChannel::capDecode))
306 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
313 for (; i != m_demux.end(); ++i, ++n)
315 int is_decode = n < 2;
317 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
319 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
321 if ((cap & iDVBChannel::capDecode) && !is_decode)
324 demux = new eDVBAllocatedDemux(i);
326 demux->get().setSourceFrontend(fe->m_frontend->getID());
328 demux->get().setSourcePVR(0);
332 eDebug("demux not found");
336 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
342 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
351 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
353 /* first, check if a channel is already existing. */
355 if (m_cached_channel)
357 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
358 if(channelid==cache_chan->getChannelID())
360 eDebug("use cached_channel");
361 channel = m_cached_channel;
364 m_cached_channel_state_changed_conn.disconnect();
366 m_releaseCachedChannelTimer.stop();
369 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
370 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
372 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
373 if (i->m_channel_id == channelid)
375 // eDebug("found shared channel..");
376 channel = i->m_channel;
381 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
385 eDebug("no channel list set!");
389 ePtr<iDVBFrontendParameters> feparm;
390 if (m_list->getChannelFrontendData(channelid, feparm))
392 eDebug("channel not found!");
396 /* allocate a frontend. */
398 ePtr<eDVBAllocatedFrontend> fe;
400 if (allocateFrontend(fe, feparm))
401 return errNoFrontend;
404 ePtr<eDVBChannel> ch;
405 ch = new eDVBChannel(this, fe);
407 res = ch->setChannel(channelid, feparm);
411 return errChidNotFound;
413 m_cached_channel = channel = ch;
414 m_cached_channel_state_changed_conn =
415 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
420 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
423 chan->getState(state);
426 case iDVBChannel::state_release:
427 case iDVBChannel::state_ok:
429 eDebug("stop release channel timer");
430 m_releaseCachedChannelTimer.stop();
433 case iDVBChannel::state_last_instance:
435 eDebug("start release channel timer");
436 m_releaseCachedChannelTimer.start(3000, true);
439 default: // ignore all other events
444 void eDVBResourceManager::releaseCachedChannel()
446 eDebug("release cached channel (timer timeout)");
450 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
452 ePtr<eDVBAllocatedFrontend> fe;
454 if (m_cached_channel)
456 m_cached_channel_state_changed_conn.disconnect();
458 m_releaseCachedChannelTimer.stop();
461 if (allocateFrontendByIndex(fe, frontend_index))
462 return errNoFrontend;
465 ch = new eDVBChannel(this, fe);
472 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
474 ePtr<eDVBAllocatedDemux> demux;
476 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
478 m_cached_channel_state_changed_conn.disconnect();
480 m_releaseCachedChannelTimer.stop();
484 ch = new eDVBChannel(this, 0);
490 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
492 m_active_channels.push_back(active_channel(chid, ch));
493 /* emit */ m_channelAdded(ch);
497 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
500 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
502 if (i->m_channel == ch)
504 i = m_active_channels.erase(i);
515 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
517 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
521 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
523 ePtr<eDVBRegisteredFrontend> best;
526 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
529 int c = i->m_frontend->isCompatibleWith(feparm);
537 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
540 if (m_cached_channel)
542 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
543 if(channelid==cache_chan->getChannelID())
547 /* first, check if a channel is already existing. */
548 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
549 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
551 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
552 if (i->m_channel_id == channelid)
554 // eDebug("found shared channel..");
559 int *decremented_cached_channel_fe_usecount=NULL,
560 *decremented_fe_usecount=NULL;
562 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
564 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
565 if (i->m_channel_id == ignore)
567 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
568 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
569 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
570 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
571 // or 2 when the cached channel is not equal to the compared channel
572 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
574 ePtr<iDVBFrontend> fe;
575 if (!i->m_channel->getFrontend(fe))
577 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
579 if ( &(*fe) == &(*ii->m_frontend) )
582 decremented_fe_usecount = &ii->m_inuse;
583 if (channel == &(*m_cached_channel))
584 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
594 if (!decremented_cached_channel_fe_usecount)
596 if (m_cached_channel)
598 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
599 if (channel->getUseCount() == 1)
601 ePtr<iDVBFrontend> fe;
602 if (!channel->getFrontend(fe))
604 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
606 if ( &(*fe) == &(*ii->m_frontend) )
609 decremented_cached_channel_fe_usecount = &ii->m_inuse;
618 decremented_cached_channel_fe_usecount=NULL;
620 ePtr<iDVBFrontendParameters> feparm;
624 eDebug("no channel list set!");
629 if (m_list->getChannelFrontendData(channelid, feparm))
631 eDebug("channel not found!");
636 ret = canAllocateFrontend(feparm);
639 if (decremented_fe_usecount)
640 ++(*decremented_fe_usecount);
641 if (decremented_cached_channel_fe_usecount)
642 ++(*decremented_cached_channel_fe_usecount);
647 DEFINE_REF(eDVBChannel);
649 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
651 m_frontend = frontend;
655 m_skipmode_n = m_skipmode_m = 0;
658 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
661 eDVBChannel::~eDVBChannel()
664 m_mgr->removeChannel(this);
669 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
671 int state, ourstate = 0;
673 /* if we are already in shutdown, don't change state. */
674 if (m_state == state_release)
677 if (fe->getState(state))
680 if (state == iDVBFrontend::stateLock)
682 eDebug("OURSTATE: ok");
684 } else if (state == iDVBFrontend::stateTuning)
686 eDebug("OURSTATE: tuning");
687 ourstate = state_tuning;
688 } else if (state == iDVBFrontend::stateLostLock)
690 /* on managed channels, we try to retune in order to re-acquire lock. */
691 if (m_current_frontend_parameters)
693 eDebug("OURSTATE: lost lock, trying to retune");
694 ourstate = state_tuning;
695 m_frontend->get().tune(*m_current_frontend_parameters);
697 /* on unmanaged channels, we don't do this. the client will do this. */
699 eDebug("OURSTATE: lost lock, unavailable now.");
700 ourstate = state_unavailable;
702 } else if (state == iDVBFrontend::stateFailed)
704 eDebug("OURSTATE: failed");
705 ourstate = state_failed;
707 eFatal("state unknown");
709 if (ourstate != m_state)
712 m_stateChanged(this);
716 void eDVBChannel::pvrEvent(int event)
720 case eFilePushThread::evtEOF:
721 eDebug("eDVBChannel: End of file!");
722 m_event(this, evtEOF);
724 case eFilePushThread::evtUser: /* start */
726 m_event(this, evtSOF);
731 void eDVBChannel::cueSheetEvent(int event)
735 case eCueSheet::evtSeek:
737 flushPVR(m_cue->m_decoding_demux);
739 case eCueSheet::evtSkipmode:
742 eSingleLocker l(m_cue->m_lock);
743 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
744 if (m_cue->m_skipmode_ratio)
746 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
747 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
748 /* i agree that this might look a bit like black magic. */
749 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
750 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
752 if (m_cue->m_skipmode_ratio < 0)
753 m_skipmode_m -= m_skipmode_n;
755 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
757 if (abs(m_skipmode_m) < abs(m_skipmode_n))
759 eWarning("something is wrong with this calculation");
760 m_skipmode_n = m_skipmode_m = 0;
765 eDebug("skipmode ratio is 0, normal play");
766 m_skipmode_n = m_skipmode_m = 0;
769 flushPVR(m_cue->m_decoding_demux);
772 case eCueSheet::evtSpanChanged:
774 m_source_span.clear();
775 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
777 off_t offset_in, offset_out;
778 pts_t pts_in = i->first, pts_out = i->second;
779 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
781 eDebug("span translation failed.\n");
784 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
785 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
792 /* remember, this gets called from another thread. */
793 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
795 unsigned int max = 10*1024*1024;
799 eDebug("no cue sheet. forcing normal play");
800 start = current_offset;
805 eSingleLocker l(m_cue->m_lock);
807 if (!m_cue->m_decoding_demux)
809 start = current_offset;
811 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
817 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
821 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
823 current_offset += m_skipmode_m;
825 while (!m_cue->m_seek_requests.empty())
827 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
828 m_cue->m_seek_requests.pop_front();
829 int relative = seek.first;
830 pts_t pts = seek.second;
835 if (!m_cue->m_decoder)
837 eDebug("no decoder - can't seek relative");
840 if (m_cue->m_decoder->getPTS(0, now))
842 eDebug("decoder getPTS failed, can't seek relative");
845 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
847 eDebug("seekTo: getCurrentPosition failed!");
852 if (relative == 1) /* pts relative */
863 if (relative == 2) /* AP relative */
865 eDebug("AP relative seeking: %lld, at %lld", pts, now);
867 if (m_tstools.getNextAccessPoint(nextap, now, pts))
870 eDebug("AP relative seeking failed!");
873 eDebug("next ap is %llx\n", pts);
879 if (m_tstools.getOffset(offset, pts))
882 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
883 current_offset = offset;
886 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
888 if ((current_offset >= i->first) && (current_offset < i->second))
890 start = current_offset;
891 /* max can not exceed max(size_t). i->second - current_offset, however, can. */
892 if ((i->second - current_offset) > max)
895 size = i->second - current_offset;
896 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
899 if (current_offset < i->first)
901 /* ok, our current offset is in an 'out' zone. */
902 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
904 /* in normal playback, just start at the next zone. */
907 /* size is not 64bit! */
908 if ((i->second - i->first) > max)
911 size = i->second - i->first;
914 if (m_skipmode_m < 0)
916 eDebug("reached SOF");
919 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
923 /* when skipping reverse, however, choose the zone before. */
925 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
928 if ((i->second - i->first) > max)
931 len = i->second - i->first;
933 start = i->second - len;
934 eDebug("skipping to %llx, %d", start, len);
940 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
942 eDebug("reached SOF");
944 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
947 start = current_offset;
949 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
953 void eDVBChannel::AddUse()
955 if (++m_use_count > 1 && m_state == state_last_instance)
958 m_stateChanged(this);
962 void eDVBChannel::ReleaseUse()
966 m_state = state_release;
967 m_stateChanged(this);
969 else if (m_use_count == 1)
971 m_state = state_last_instance;
972 m_stateChanged(this);
976 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
979 m_mgr->removeChannel(this);
986 eDebug("no frontend to tune!");
990 m_channel_id = channelid;
991 m_mgr->addChannel(channelid, this);
992 m_state = state_tuning;
993 /* if tuning fails, shutdown the channel immediately. */
995 res = m_frontend->get().tune(*feparm);
996 m_current_frontend_parameters = feparm;
1000 m_state = state_release;
1001 m_stateChanged(this);
1008 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1010 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1014 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1016 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1020 RESULT eDVBChannel::getState(int &state)
1026 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1031 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1033 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1039 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1044 /* don't hold a reference to the decoding demux, we don't need it. */
1046 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1047 the refcount is lost. thus, decoding demuxes are never allocated.
1049 this poses a big problem for PiP. */
1050 if (cap & capDecode)
1055 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1060 frontend = &m_frontend->get();
1066 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1068 param = m_current_frontend_parameters;
1072 RESULT eDVBChannel::playFile(const char *file)
1074 ASSERT(!m_frontend);
1077 m_pvr_thread->stop();
1078 delete m_pvr_thread;
1082 m_tstools.openFile(file);
1084 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1085 THEN DO A REAL FIX HERE! */
1087 /* (this codepath needs to be improved anyway.) */
1088 #if HAVE_DVB_API_VERSION < 3
1089 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1091 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1093 if (m_pvr_fd_dst < 0)
1095 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1099 m_pvr_thread = new eFilePushThread();
1100 m_pvr_thread->enablePVRCommit(1);
1101 m_pvr_thread->setScatterGather(this);
1103 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1105 delete m_pvr_thread;
1107 eDebug("can't open PVR file %s (%m)", file);
1110 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1113 m_stateChanged(this);
1118 void eDVBChannel::stopFile()
1122 m_pvr_thread->stop();
1123 ::close(m_pvr_fd_dst);
1124 delete m_pvr_thread;
1129 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1131 m_conn_cueSheetEvent = 0;
1134 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1137 RESULT eDVBChannel::getLength(pts_t &len)
1139 return m_tstools.calcLen(len);
1142 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1144 if (!decoding_demux)
1151 if (mode == 0) /* demux */
1153 r = decoding_demux->getSTC(now, 0);
1156 eDebug("demux getSTC failed");
1160 now = pos; /* fixup supplied */
1162 off_t off = 0; /* TODO: fixme */
1163 r = m_tstools.fixupPTS(off, now);
1166 eDebug("fixup PTS failed");
1175 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1177 /* when seeking, we have to ensure that all buffers are flushed.
1178 there are basically 3 buffers:
1179 a.) the filepush's internal buffer
1180 b.) the PVR buffer (before demux)
1181 c.) the ratebuffer (after demux)
1183 it's important to clear them in the correct order, otherwise
1184 the ratebuffer (for example) would immediately refill from
1185 the not-yet-flushed PVR buffer.
1188 m_pvr_thread->pause();
1189 /* flush internal filepush buffer */
1190 m_pvr_thread->flush();
1191 /* HACK: flush PVR buffer */
1192 ::ioctl(m_pvr_fd_dst, 0);
1194 /* flush ratebuffers (video, audio) */
1196 decoding_demux->flush();
1198 /* demux will also flush all decoder.. */
1199 /* resume will re-query the SG */
1200 m_pvr_thread->resume();
1203 DEFINE_REF(eCueSheet);
1205 eCueSheet::eCueSheet()
1207 m_skipmode_ratio = 0;
1210 void eCueSheet::seekTo(int relative, const pts_t &pts)
1213 eSingleLocker l(m_lock);
1214 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1219 void eCueSheet::clear()
1221 eSingleLocker l(m_lock);
1225 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1228 eSingleLocker l(m_lock);
1229 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1233 void eCueSheet::commitSpans()
1235 m_event(evtSpanChanged);
1238 void eCueSheet::setSkipmode(const pts_t &ratio)
1241 eSingleLocker l(m_lock);
1242 m_skipmode_ratio = ratio;
1244 m_event(evtSkipmode);
1247 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1249 m_decoding_demux = demux;
1250 m_decoder = decoder;
1253 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1255 connection = new eConnection(this, m_event.connect(event));