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!");
850 } else if (pts < 0) /* seek relative to end */
855 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
859 eWarning("getLength failed - can't seek relative to end!");
864 if (relative == 1) /* pts relative */
875 if (relative == 2) /* AP relative */
877 eDebug("AP relative seeking: %lld, at %lld", pts, now);
879 if (m_tstools.getNextAccessPoint(nextap, now, pts))
882 eDebug("AP relative seeking failed!");
885 eDebug("next ap is %llx\n", pts);
891 if (m_tstools.getOffset(offset, pts))
893 eDebug("get offset for pts=%lld failed!", pts);
897 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
898 current_offset = offset;
901 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
903 if ((current_offset >= i->first) && (current_offset < i->second))
905 start = current_offset;
906 /* max can not exceed max(size_t). i->second - current_offset, however, can. */
907 if ((i->second - current_offset) > max)
910 size = i->second - current_offset;
911 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
914 if (current_offset < i->first)
916 /* ok, our current offset is in an 'out' zone. */
917 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
919 /* in normal playback, just start at the next zone. */
922 /* size is not 64bit! */
923 if ((i->second - i->first) > max)
926 size = i->second - i->first;
929 if (m_skipmode_m < 0)
931 eDebug("reached SOF");
934 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
938 /* when skipping reverse, however, choose the zone before. */
940 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
943 if ((i->second - i->first) > max)
946 len = i->second - i->first;
948 start = i->second - len;
949 eDebug("skipping to %llx, %d", start, len);
955 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
957 eDebug("reached SOF");
959 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
962 start = current_offset;
964 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
968 void eDVBChannel::AddUse()
970 if (++m_use_count > 1 && m_state == state_last_instance)
973 m_stateChanged(this);
977 void eDVBChannel::ReleaseUse()
981 m_state = state_release;
982 m_stateChanged(this);
984 else if (m_use_count == 1)
986 m_state = state_last_instance;
987 m_stateChanged(this);
991 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
994 m_mgr->removeChannel(this);
1001 eDebug("no frontend to tune!");
1005 m_channel_id = channelid;
1006 m_mgr->addChannel(channelid, this);
1007 m_state = state_tuning;
1008 /* if tuning fails, shutdown the channel immediately. */
1010 res = m_frontend->get().tune(*feparm);
1011 m_current_frontend_parameters = feparm;
1015 m_state = state_release;
1016 m_stateChanged(this);
1023 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1025 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1029 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1031 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1035 RESULT eDVBChannel::getState(int &state)
1041 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1046 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1048 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1054 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1059 /* don't hold a reference to the decoding demux, we don't need it. */
1061 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1062 the refcount is lost. thus, decoding demuxes are never allocated.
1064 this poses a big problem for PiP. */
1065 if (cap & capDecode)
1070 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1075 frontend = &m_frontend->get();
1081 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1083 param = m_current_frontend_parameters;
1087 RESULT eDVBChannel::playFile(const char *file)
1089 ASSERT(!m_frontend);
1092 m_pvr_thread->stop();
1093 delete m_pvr_thread;
1097 m_tstools.openFile(file);
1099 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1100 THEN DO A REAL FIX HERE! */
1102 /* (this codepath needs to be improved anyway.) */
1103 #if HAVE_DVB_API_VERSION < 3
1104 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1106 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1108 if (m_pvr_fd_dst < 0)
1110 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1114 m_pvr_thread = new eFilePushThread();
1115 m_pvr_thread->enablePVRCommit(1);
1116 m_pvr_thread->setScatterGather(this);
1118 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1120 delete m_pvr_thread;
1122 eDebug("can't open PVR file %s (%m)", file);
1125 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1128 m_stateChanged(this);
1133 void eDVBChannel::stopFile()
1137 m_pvr_thread->stop();
1138 ::close(m_pvr_fd_dst);
1139 delete m_pvr_thread;
1144 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1146 m_conn_cueSheetEvent = 0;
1149 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1152 RESULT eDVBChannel::getLength(pts_t &len)
1154 return m_tstools.calcLen(len);
1157 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1159 if (!decoding_demux)
1166 if (mode == 0) /* demux */
1168 r = decoding_demux->getSTC(now, 0);
1171 eDebug("demux getSTC failed");
1175 now = pos; /* fixup supplied */
1177 off_t off = 0; /* TODO: fixme */
1178 r = m_tstools.fixupPTS(off, now);
1181 eDebug("fixup PTS failed");
1190 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1192 /* when seeking, we have to ensure that all buffers are flushed.
1193 there are basically 3 buffers:
1194 a.) the filepush's internal buffer
1195 b.) the PVR buffer (before demux)
1196 c.) the ratebuffer (after demux)
1198 it's important to clear them in the correct order, otherwise
1199 the ratebuffer (for example) would immediately refill from
1200 the not-yet-flushed PVR buffer.
1203 m_pvr_thread->pause();
1204 /* flush internal filepush buffer */
1205 m_pvr_thread->flush();
1206 /* HACK: flush PVR buffer */
1207 ::ioctl(m_pvr_fd_dst, 0);
1209 /* flush ratebuffers (video, audio) */
1211 decoding_demux->flush();
1213 /* demux will also flush all decoder.. */
1214 /* resume will re-query the SG */
1215 m_pvr_thread->resume();
1218 DEFINE_REF(eCueSheet);
1220 eCueSheet::eCueSheet()
1222 m_skipmode_ratio = 0;
1225 void eCueSheet::seekTo(int relative, const pts_t &pts)
1228 eSingleLocker l(m_lock);
1229 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1234 void eCueSheet::clear()
1236 eSingleLocker l(m_lock);
1240 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1243 eSingleLocker l(m_lock);
1244 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1248 void eCueSheet::commitSpans()
1250 m_event(evtSpanChanged);
1253 void eCueSheet::setSkipmode(const pts_t &ratio)
1256 eSingleLocker l(m_lock);
1257 m_skipmode_ratio = ratio;
1259 m_event(evtSkipmode);
1262 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1264 m_decoding_demux = demux;
1265 m_decoder = decoder;
1268 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1270 connection = new eConnection(this, m_event.connect(event));