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_ok:
374 eDebug("stop release channel timer");
375 m_releaseCachedChannelTimer.stop();
378 case iDVBChannel::state_last_instance:
380 eDebug("start release channel timer");
381 m_releaseCachedChannelTimer.start(3000, true);
384 default: // ignore all other events
389 void eDVBResourceManager::releaseCachedChannel()
391 eDebug("release cached channel");
395 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
397 ePtr<eDVBAllocatedFrontend> fe;
399 if (m_cached_channel)
402 if (allocateFrontendByIndex(fe, frontend_index))
403 return errNoFrontend;
406 ch = new eDVBChannel(this, fe);
413 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
415 ePtr<eDVBAllocatedDemux> demux;
417 if (m_cached_channel)
421 ch = new eDVBChannel(this, 0);
427 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
429 m_active_channels.push_back(active_channel(chid, ch));
430 /* emit */ m_channelAdded(ch);
434 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
437 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
439 if (i->m_channel == ch)
441 i = m_active_channels.erase(i);
452 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
454 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
458 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
460 ePtr<eDVBRegisteredFrontend> best;
463 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
466 int c = i->m_frontend->isCompatibleWith(feparm);
474 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
477 if (m_cached_channel)
479 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
480 if(channelid==cache_chan->getChannelID())
484 /* first, check if a channel is already existing. */
485 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
486 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
488 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
489 if (i->m_channel_id == channelid)
491 // eDebug("found shared channel..");
496 int *decremented_cached_channel_fe_usecount=NULL,
497 *decremented_fe_usecount=NULL;
499 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
501 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
502 if (i->m_channel_id == ignore)
504 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
505 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
507 ePtr<iDVBFrontend> fe;
508 if (!i->m_channel->getFrontend(fe))
510 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
512 if ( &(*fe) == &(*ii->m_frontend) )
515 decremented_fe_usecount = &ii->m_inuse;
516 if (channel == &(*m_cached_channel))
517 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
527 if (!decremented_cached_channel_fe_usecount)
529 if (m_cached_channel)
531 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
532 if (channel->getUseCount() == 1)
534 ePtr<iDVBFrontend> fe;
535 if (!channel->getFrontend(fe))
537 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
539 if ( &(*fe) == &(*ii->m_frontend) )
542 decremented_cached_channel_fe_usecount = &ii->m_inuse;
551 decremented_cached_channel_fe_usecount=NULL;
553 ePtr<iDVBFrontendParameters> feparm;
557 eDebug("no channel list set!");
562 if (m_list->getChannelFrontendData(channelid, feparm))
564 eDebug("channel not found!");
569 ret = canAllocateFrontend(feparm);
572 if (decremented_fe_usecount)
573 ++(*decremented_fe_usecount);
574 if (decremented_cached_channel_fe_usecount)
575 ++(*decremented_cached_channel_fe_usecount);
580 DEFINE_REF(eDVBChannel);
582 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
584 m_frontend = frontend;
588 m_skipmode_n = m_skipmode_m = 0;
591 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
594 eDVBChannel::~eDVBChannel()
597 m_mgr->removeChannel(this);
602 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
604 int state, ourstate = 0;
606 /* if we are already in shutdown, don't change state. */
607 if (m_state == state_release)
610 if (fe->getState(state))
613 if (state == iDVBFrontend::stateLock)
615 eDebug("OURSTATE: ok");
617 } else if (state == iDVBFrontend::stateTuning)
619 eDebug("OURSTATE: tuning");
620 ourstate = state_tuning;
621 } else if (state == iDVBFrontend::stateLostLock)
623 /* on managed channels, we try to retune in order to re-acquire lock. */
626 eDebug("OURSTATE: lost lock, trying to retune");
627 ourstate = state_tuning;
628 m_frontend->get().tune(*m_feparm);
630 /* on unmanaged channels, we don't do this. the client will do this. */
632 eDebug("OURSTATE: lost lock, unavailable now.");
633 ourstate = state_unavailable;
635 } else if (state == iDVBFrontend::stateFailed)
637 eDebug("OURSTATE: failed");
638 ourstate = state_failed;
640 eFatal("state unknown");
642 if (ourstate != m_state)
645 m_stateChanged(this);
649 void eDVBChannel::pvrEvent(int event)
653 case eFilePushThread::evtEOF:
654 eDebug("eDVBChannel: End of file!");
655 m_event(this, evtEOF);
657 case eFilePushThread::evtUser: /* start */
659 m_event(this, evtSOF);
664 void eDVBChannel::cueSheetEvent(int event)
668 case eCueSheet::evtSeek:
670 flushPVR(m_cue->m_decoding_demux);
672 case eCueSheet::evtSkipmode:
675 eSingleLocker l(m_cue->m_lock);
676 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
677 if (m_cue->m_skipmode_ratio)
679 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
680 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
681 /* i agree that this might look a bit like black magic. */
682 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
683 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio;
685 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
687 if (abs(m_skipmode_m) < abs(m_skipmode_n))
689 eFatal("damn, something is wrong with this calculation");
690 m_skipmode_n = m_skipmode_m = 0;
695 eDebug("skipmode ratio is 0, normal play");
696 m_skipmode_n = m_skipmode_m = 0;
699 flushPVR(m_cue->m_decoding_demux);
702 case eCueSheet::evtSpanChanged:
703 eDebug("source span translation not yet supported");
704 // recheckCuesheetSpans();
709 /* remember, this gets called from another thread. */
710 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
712 unsigned int max = 10*1024*1024;
716 eDebug("no cue sheet. forcing normal play");
717 start = current_offset;
722 eSingleLocker l(m_cue->m_lock);
724 if (!m_cue->m_decoding_demux)
726 start = current_offset;
728 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
734 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
738 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
740 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
742 eDebug("reached SOF");
744 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
747 current_offset += m_skipmode_m;
749 while (!m_cue->m_seek_requests.empty())
751 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
752 m_cue->m_seek_requests.pop_front();
753 int relative = seek.first;
754 pts_t pts = seek.second;
756 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
764 /* we're using the decoder's timestamp here. this
765 won't work for radio (ouch). */
766 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
768 eDebug("seekTo: getCurrentPosition failed!");
777 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
779 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
780 current_offset = offset;
783 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
785 if ((current_offset >= i->first) && (current_offset < i->second))
787 start = current_offset;
788 size = i->second - current_offset;
791 eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
794 if (current_offset < i->first)
797 size = i->second - i->first;
805 start = current_offset;
807 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
814 void eDVBChannel::AddUse()
816 if (++m_use_count > 1 && m_state == state_last_instance)
820 void eDVBChannel::ReleaseUse()
824 m_state = state_release;
825 m_stateChanged(this);
827 else if (m_use_count == 1)
829 m_state = state_last_instance;
830 m_stateChanged(this);
834 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
837 m_mgr->removeChannel(this);
844 eDebug("no frontend to tune!");
848 m_channel_id = channelid;
849 m_mgr->addChannel(channelid, this);
850 m_state = state_tuning;
851 /* if tuning fails, shutdown the channel immediately. */
853 res = m_frontend->get().tune(*feparm);
858 m_state = state_release;
859 m_stateChanged(this);
866 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
868 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
872 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
874 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
878 RESULT eDVBChannel::getState(int &state)
884 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
889 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
891 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
897 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
902 /* don't hold a reference to the decoding demux, we don't need it. */
908 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
910 frontend = &m_frontend->get();
917 RESULT eDVBChannel::playFile(const char *file)
922 m_pvr_thread->stop();
927 m_tstools.openFile(file);
929 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
930 THEN DO A REAL FIX HERE! */
932 /* (this codepath needs to be improved anyway.) */
933 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
934 if (m_pvr_fd_dst < 0)
936 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
940 m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
941 if (m_pvr_fd_src < 0)
943 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
949 m_stateChanged(this);
951 m_pvr_thread = new eFilePushThread();
952 m_pvr_thread->enablePVRCommit(1);
953 m_pvr_thread->setScatterGather(this);
955 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
956 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
961 void eDVBChannel::stopFile()
965 m_pvr_thread->stop();
966 ::close(m_pvr_fd_src);
967 ::close(m_pvr_fd_dst);
973 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
975 m_conn_cueSheetEvent = 0;
978 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
981 RESULT eDVBChannel::getLength(pts_t &len)
983 return m_tstools.calcLen(len);
986 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
992 /* getPTS for offset 0 is cached, so it doesn't harm. */
993 int r = m_tstools.getPTS(begin, pos);
996 eDebug("tstools getpts(0) failed!");
1002 /* TODO: this is a gross hack. */
1003 r = decoding_demux->getSTC(now, mode ? 128 : 0);
1007 eDebug("demux getSTC failed");
1011 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
1012 /* when we are less than 10 seconds before the start, return 0. */
1013 /* (we're just waiting for the timespam to start) */
1014 if ((now < pos) && ((pos - now) < 90000 * 10))
1020 if (now < pos) /* wrap around */
1021 pos = now + ((pts_t)1)<<33 - pos;
1028 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1030 /* when seeking, we have to ensure that all buffers are flushed.
1031 there are basically 3 buffers:
1032 a.) the filepush's internal buffer
1033 b.) the PVR buffer (before demux)
1034 c.) the ratebuffer (after demux)
1036 it's important to clear them in the correct order, otherwise
1037 the ratebuffer (for example) would immediately refill from
1038 the not-yet-flushed PVR buffer.
1041 m_pvr_thread->pause();
1042 /* flush internal filepush buffer */
1043 m_pvr_thread->flush();
1044 /* HACK: flush PVR buffer */
1045 ::ioctl(m_pvr_fd_dst, 0);
1047 /* flush ratebuffers (video, audio) */
1049 decoding_demux->flush();
1051 /* demux will also flush all decoder.. */
1052 /* resume will re-query the SG */
1053 m_pvr_thread->resume();
1056 DEFINE_REF(eCueSheet);
1058 eCueSheet::eCueSheet()
1060 m_skipmode_ratio = 0;
1063 void eCueSheet::seekTo(int relative, const pts_t &pts)
1066 eSingleLock l(m_lock);
1067 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1072 void eCueSheet::clear()
1074 eSingleLock l(m_lock);
1078 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1081 eSingleLock l(m_lock);
1082 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1084 m_event(evtSpanChanged);
1087 void eCueSheet::setSkipmode(const pts_t &ratio)
1090 eSingleLock l(m_lock);
1091 m_skipmode_ratio = ratio;
1093 m_event(evtSkipmode);
1096 void eCueSheet::setDecodingDemux(iDVBDemux *demux)
1098 m_decoding_demux = demux;
1101 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1103 connection = new eConnection(this, m_event.connect(event));