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()
46 :m_releaseCachedChannelTimer(eApp)
50 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
54 /* search available adapters... */
59 while (eDVBAdapterLinux::exist(num_adapter))
61 addAdapter(new eDVBAdapterLinux(num_adapter));
65 eDebug("found %d adapter, %d frontends and %d demux",
66 m_adapter.size(), m_frontend.size(), m_demux.size());
68 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
72 DEFINE_REF(eDVBAdapterLinux);
73 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
78 eDebug("scanning for frontends..");
83 #if HAVE_DVB_API_VERSION < 3
84 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
86 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
88 if (stat(filename, &s))
90 ePtr<eDVBFrontend> fe;
93 fe = new eDVBFrontend(m_nr, num_fe, ok);
95 m_frontend.push_back(fe);
105 #if HAVE_DVB_API_VERSION < 3
106 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
108 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
110 if (stat(filename, &s))
112 ePtr<eDVBDemux> demux;
114 demux = new eDVBDemux(m_nr, num_demux);
115 m_demux.push_back(demux);
121 int eDVBAdapterLinux::getNumDemux()
123 return m_demux.size();
126 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
128 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
129 while (nr && (i != m_demux.end()))
135 if (i != m_demux.end())
143 int eDVBAdapterLinux::getNumFrontends()
145 return m_frontend.size();
148 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
150 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
151 while (nr && (i != m_frontend.end()))
157 if (i != m_frontend.end())
165 int eDVBAdapterLinux::exist(int nr)
169 #if HAVE_DVB_API_VERSION < 3
170 sprintf(filename, "/dev/dvb/card%d", nr);
172 sprintf(filename, "/dev/dvb/adapter%d", nr);
174 if (!stat(filename, &s))
179 eDVBResourceManager::~eDVBResourceManager()
181 if (instance == this)
185 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
187 int num_fe = adapter->getNumFrontends();
188 int num_demux = adapter->getNumDemux();
190 m_adapter.push_back(adapter);
193 for (i=0; i<num_demux; ++i)
195 ePtr<eDVBDemux> demux;
196 if (!adapter->getDemux(demux, i))
197 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
200 for (i=0; i<num_fe; ++i)
202 ePtr<eDVBFrontend> frontend;
204 if (!adapter->getFrontend(frontend, i))
206 frontend->setSEC(m_sec);
207 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
212 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
214 ePtr<eDVBRegisteredFrontend> best;
217 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
220 int c = i->m_frontend->isCompatibleWith(feparm);
230 fe = new eDVBAllocatedFrontend(best);
239 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
241 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
242 if ((!nr) && !i->m_inuse)
244 fe = new eDVBAllocatedFrontend(i);
252 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
254 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
255 never use the first one unless we need a decoding demux. */
257 eDebug("allocate demux");
258 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
260 if (i == m_demux.end())
264 /* FIXME: hardware demux policy */
265 if (!(cap & iDVBChannel::capDecode))
268 for (; i != m_demux.end(); ++i, ++n)
269 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
271 if ((cap & iDVBChannel::capDecode) && n)
274 demux = new eDVBAllocatedDemux(i);
276 demux->get().setSourceFrontend(fe->m_frontend->getID());
278 demux->get().setSourcePVR(0);
281 eDebug("demux not found");
285 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
291 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
300 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
302 /* first, check if a channel is already existing. */
304 if (m_cached_channel)
306 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
307 if(channelid==cache_chan->getChannelID())
309 eDebug("use cached_channel");
310 channel = m_cached_channel;
316 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
317 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
319 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
320 if (i->m_channel_id == channelid)
322 // eDebug("found shared channel..");
323 channel = i->m_channel;
328 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
332 eDebug("no channel list set!");
336 ePtr<iDVBFrontendParameters> feparm;
337 if (m_list->getChannelFrontendData(channelid, feparm))
339 eDebug("channel not found!");
343 /* allocate a frontend. */
345 ePtr<eDVBAllocatedFrontend> fe;
347 if (allocateFrontend(fe, feparm))
348 return errNoFrontend;
351 ePtr<eDVBChannel> ch;
352 ch = new eDVBChannel(this, fe);
354 res = ch->setChannel(channelid, feparm);
358 return errChidNotFound;
360 m_cached_channel = channel = ch;
361 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
366 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
369 chan->getState(state);
372 case iDVBChannel::state_release:
373 case iDVBChannel::state_ok:
375 eDebug("stop release channel timer");
376 m_releaseCachedChannelTimer.stop();
379 case iDVBChannel::state_last_instance:
381 eDebug("start release channel timer");
382 m_releaseCachedChannelTimer.start(3000, true);
385 default: // ignore all other events
390 void eDVBResourceManager::releaseCachedChannel()
392 eDebug("release cached channel");
396 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
398 ePtr<eDVBAllocatedFrontend> fe;
400 if (m_cached_channel)
403 if (allocateFrontendByIndex(fe, frontend_index))
404 return errNoFrontend;
407 ch = new eDVBChannel(this, fe);
414 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
416 ePtr<eDVBAllocatedDemux> demux;
418 if (m_cached_channel)
422 ch = new eDVBChannel(this, 0);
428 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
430 m_active_channels.push_back(active_channel(chid, ch));
431 /* emit */ m_channelAdded(ch);
435 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
438 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
440 if (i->m_channel == ch)
442 i = m_active_channels.erase(i);
453 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
455 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
459 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
461 ePtr<eDVBRegisteredFrontend> best;
464 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
467 int c = i->m_frontend->isCompatibleWith(feparm);
475 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
478 if (m_cached_channel)
480 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
481 if(channelid==cache_chan->getChannelID())
485 /* first, check if a channel is already existing. */
486 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
487 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
489 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
490 if (i->m_channel_id == channelid)
492 // eDebug("found shared channel..");
497 int *decremented_cached_channel_fe_usecount=NULL,
498 *decremented_fe_usecount=NULL;
500 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
502 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
503 if (i->m_channel_id == ignore)
505 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
506 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
508 ePtr<iDVBFrontend> fe;
509 if (!i->m_channel->getFrontend(fe))
511 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
513 if ( &(*fe) == &(*ii->m_frontend) )
516 decremented_fe_usecount = &ii->m_inuse;
517 if (channel == &(*m_cached_channel))
518 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
528 if (!decremented_cached_channel_fe_usecount)
530 if (m_cached_channel)
532 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
533 if (channel->getUseCount() == 1)
535 ePtr<iDVBFrontend> fe;
536 if (!channel->getFrontend(fe))
538 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
540 if ( &(*fe) == &(*ii->m_frontend) )
543 decremented_cached_channel_fe_usecount = &ii->m_inuse;
552 decremented_cached_channel_fe_usecount=NULL;
554 ePtr<iDVBFrontendParameters> feparm;
558 eDebug("no channel list set!");
563 if (m_list->getChannelFrontendData(channelid, feparm))
565 eDebug("channel not found!");
570 ret = canAllocateFrontend(feparm);
573 if (decremented_fe_usecount)
574 ++(*decremented_fe_usecount);
575 if (decremented_cached_channel_fe_usecount)
576 ++(*decremented_cached_channel_fe_usecount);
581 DEFINE_REF(eDVBChannel);
583 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
585 m_frontend = frontend;
589 m_skipmode_n = m_skipmode_m = 0;
592 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
595 eDVBChannel::~eDVBChannel()
598 m_mgr->removeChannel(this);
603 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
605 int state, ourstate = 0;
607 /* if we are already in shutdown, don't change state. */
608 if (m_state == state_release)
611 if (fe->getState(state))
614 if (state == iDVBFrontend::stateLock)
616 eDebug("OURSTATE: ok");
618 } else if (state == iDVBFrontend::stateTuning)
620 eDebug("OURSTATE: tuning");
621 ourstate = state_tuning;
622 } else if (state == iDVBFrontend::stateLostLock)
624 /* on managed channels, we try to retune in order to re-acquire lock. */
627 eDebug("OURSTATE: lost lock, trying to retune");
628 ourstate = state_tuning;
629 m_frontend->get().tune(*m_feparm);
631 /* on unmanaged channels, we don't do this. the client will do this. */
633 eDebug("OURSTATE: lost lock, unavailable now.");
634 ourstate = state_unavailable;
636 } else if (state == iDVBFrontend::stateFailed)
638 eDebug("OURSTATE: failed");
639 ourstate = state_failed;
641 eFatal("state unknown");
643 if (ourstate != m_state)
646 m_stateChanged(this);
650 void eDVBChannel::pvrEvent(int event)
654 case eFilePushThread::evtEOF:
655 eDebug("eDVBChannel: End of file!");
656 m_event(this, evtEOF);
658 case eFilePushThread::evtUser: /* start */
660 m_event(this, evtSOF);
665 void eDVBChannel::cueSheetEvent(int event)
669 case eCueSheet::evtSeek:
671 flushPVR(m_cue->m_decoding_demux);
673 case eCueSheet::evtSkipmode:
676 eSingleLocker l(m_cue->m_lock);
677 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
678 if (m_cue->m_skipmode_ratio)
680 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
681 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
682 /* i agree that this might look a bit like black magic. */
683 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
684 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio;
686 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
688 if (abs(m_skipmode_m) < abs(m_skipmode_n))
690 eFatal("damn, something is wrong with this calculation");
691 m_skipmode_n = m_skipmode_m = 0;
696 eDebug("skipmode ratio is 0, normal play");
697 m_skipmode_n = m_skipmode_m = 0;
700 flushPVR(m_cue->m_decoding_demux);
703 case eCueSheet::evtSpanChanged:
704 eDebug("source span translation not yet supported");
705 // recheckCuesheetSpans();
710 /* remember, this gets called from another thread. */
711 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
713 unsigned int max = 10*1024*1024;
717 eDebug("no cue sheet. forcing normal play");
718 start = current_offset;
723 eSingleLocker l(m_cue->m_lock);
725 if (!m_cue->m_decoding_demux)
727 start = current_offset;
729 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
735 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
739 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
741 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
743 eDebug("reached SOF");
745 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
748 current_offset += m_skipmode_m;
750 while (!m_cue->m_seek_requests.empty())
752 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
753 m_cue->m_seek_requests.pop_front();
754 int relative = seek.first;
755 pts_t pts = seek.second;
757 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
765 /* we're using the decoder's timestamp here. this
766 won't work for radio (ouch). */
767 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
769 eDebug("seekTo: getCurrentPosition failed!");
778 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
780 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
781 current_offset = offset;
784 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
786 if ((current_offset >= i->first) && (current_offset < i->second))
788 start = current_offset;
789 size = i->second - current_offset;
792 eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
795 if (current_offset < i->first)
798 size = i->second - i->first;
806 start = current_offset;
808 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
815 void eDVBChannel::AddUse()
817 if (++m_use_count > 1 && m_state == state_last_instance)
820 m_stateChanged(this);
824 void eDVBChannel::ReleaseUse()
828 m_state = state_release;
829 m_stateChanged(this);
831 else if (m_use_count == 1)
833 m_state = state_last_instance;
834 m_stateChanged(this);
838 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
841 m_mgr->removeChannel(this);
848 eDebug("no frontend to tune!");
852 m_channel_id = channelid;
853 m_mgr->addChannel(channelid, this);
854 m_state = state_tuning;
855 /* if tuning fails, shutdown the channel immediately. */
857 res = m_frontend->get().tune(*feparm);
862 m_state = state_release;
863 m_stateChanged(this);
870 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
872 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
876 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
878 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
882 RESULT eDVBChannel::getState(int &state)
888 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
893 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
895 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
901 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
906 /* don't hold a reference to the decoding demux, we don't need it. */
912 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
914 frontend = &m_frontend->get();
921 RESULT eDVBChannel::playFile(const char *file)
926 m_pvr_thread->stop();
931 m_tstools.openFile(file);
933 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
934 THEN DO A REAL FIX HERE! */
936 /* (this codepath needs to be improved anyway.) */
937 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
938 if (m_pvr_fd_dst < 0)
940 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
944 m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
945 if (m_pvr_fd_src < 0)
947 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
953 m_stateChanged(this);
955 m_pvr_thread = new eFilePushThread();
956 m_pvr_thread->enablePVRCommit(1);
957 m_pvr_thread->setScatterGather(this);
959 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
960 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
965 void eDVBChannel::stopFile()
969 m_pvr_thread->stop();
970 ::close(m_pvr_fd_src);
971 ::close(m_pvr_fd_dst);
977 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
979 m_conn_cueSheetEvent = 0;
982 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
985 RESULT eDVBChannel::getLength(pts_t &len)
987 return m_tstools.calcLen(len);
990 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
996 /* getPTS for offset 0 is cached, so it doesn't harm. */
997 int r = m_tstools.getPTS(begin, pos);
1000 eDebug("tstools getpts(0) failed!");
1006 /* TODO: this is a gross hack. */
1007 r = decoding_demux->getSTC(now, mode ? 128 : 0);
1011 eDebug("demux getSTC failed");
1015 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
1016 /* when we are less than 10 seconds before the start, return 0. */
1017 /* (we're just waiting for the timespam to start) */
1018 if ((now < pos) && ((pos - now) < 90000 * 10))
1024 if (now < pos) /* wrap around */
1025 pos = now + ((pts_t)1)<<33 - pos;
1032 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1034 /* when seeking, we have to ensure that all buffers are flushed.
1035 there are basically 3 buffers:
1036 a.) the filepush's internal buffer
1037 b.) the PVR buffer (before demux)
1038 c.) the ratebuffer (after demux)
1040 it's important to clear them in the correct order, otherwise
1041 the ratebuffer (for example) would immediately refill from
1042 the not-yet-flushed PVR buffer.
1045 m_pvr_thread->pause();
1046 /* flush internal filepush buffer */
1047 m_pvr_thread->flush();
1048 /* HACK: flush PVR buffer */
1049 ::ioctl(m_pvr_fd_dst, 0);
1051 /* flush ratebuffers (video, audio) */
1053 decoding_demux->flush();
1055 /* demux will also flush all decoder.. */
1056 /* resume will re-query the SG */
1057 m_pvr_thread->resume();
1060 DEFINE_REF(eCueSheet);
1062 eCueSheet::eCueSheet()
1064 m_skipmode_ratio = 0;
1067 void eCueSheet::seekTo(int relative, const pts_t &pts)
1070 eSingleLock l(m_lock);
1071 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1076 void eCueSheet::clear()
1078 eSingleLock l(m_lock);
1082 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1085 eSingleLock l(m_lock);
1086 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1088 m_event(evtSpanChanged);
1091 void eCueSheet::setSkipmode(const pts_t &ratio)
1094 eSingleLock l(m_lock);
1095 m_skipmode_ratio = ratio;
1097 m_event(evtSkipmode);
1100 void eCueSheet::setDecodingDemux(iDVBDemux *demux)
1102 m_decoding_demux = demux;
1105 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1107 connection = new eConnection(this, m_event.connect(event));