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;
313 m_cached_channel_state_changed_conn.disconnect();
317 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
318 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
320 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
321 if (i->m_channel_id == channelid)
323 // eDebug("found shared channel..");
324 channel = i->m_channel;
329 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
333 eDebug("no channel list set!");
337 ePtr<iDVBFrontendParameters> feparm;
338 if (m_list->getChannelFrontendData(channelid, feparm))
340 eDebug("channel not found!");
344 /* allocate a frontend. */
346 ePtr<eDVBAllocatedFrontend> fe;
348 if (allocateFrontend(fe, feparm))
349 return errNoFrontend;
352 ePtr<eDVBChannel> ch;
353 ch = new eDVBChannel(this, fe);
355 res = ch->setChannel(channelid, feparm);
359 return errChidNotFound;
361 m_cached_channel = channel = ch;
362 m_cached_channel_state_changed_conn =
363 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
368 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
371 chan->getState(state);
374 case iDVBChannel::state_release:
375 case iDVBChannel::state_ok:
377 eDebug("stop release channel timer");
378 m_releaseCachedChannelTimer.stop();
381 case iDVBChannel::state_last_instance:
383 eDebug("start release channel timer");
384 m_releaseCachedChannelTimer.start(3000, true);
387 default: // ignore all other events
392 void eDVBResourceManager::releaseCachedChannel()
394 eDebug("release cached channel");
395 m_cached_channel_state_changed_conn.disconnect();
399 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
401 ePtr<eDVBAllocatedFrontend> fe;
403 if (m_cached_channel)
405 m_cached_channel_state_changed_conn.disconnect();
409 if (allocateFrontendByIndex(fe, frontend_index))
410 return errNoFrontend;
413 ch = new eDVBChannel(this, fe);
420 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
422 ePtr<eDVBAllocatedDemux> demux;
424 if (m_cached_channel)
426 m_cached_channel_state_changed_conn.disconnect();
431 ch = new eDVBChannel(this, 0);
437 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
439 m_active_channels.push_back(active_channel(chid, ch));
440 /* emit */ m_channelAdded(ch);
444 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
447 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
449 if (i->m_channel == ch)
451 i = m_active_channels.erase(i);
462 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
464 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
468 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
470 ePtr<eDVBRegisteredFrontend> best;
473 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
476 int c = i->m_frontend->isCompatibleWith(feparm);
484 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
487 if (m_cached_channel)
489 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
490 if(channelid==cache_chan->getChannelID())
494 /* first, check if a channel is already existing. */
495 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
496 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
498 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
499 if (i->m_channel_id == channelid)
501 // eDebug("found shared channel..");
506 int *decremented_cached_channel_fe_usecount=NULL,
507 *decremented_fe_usecount=NULL;
509 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
511 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
512 if (i->m_channel_id == ignore)
514 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
515 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
517 ePtr<iDVBFrontend> fe;
518 if (!i->m_channel->getFrontend(fe))
520 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
522 if ( &(*fe) == &(*ii->m_frontend) )
525 decremented_fe_usecount = &ii->m_inuse;
526 if (channel == &(*m_cached_channel))
527 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
537 if (!decremented_cached_channel_fe_usecount)
539 if (m_cached_channel)
541 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
542 if (channel->getUseCount() == 1)
544 ePtr<iDVBFrontend> fe;
545 if (!channel->getFrontend(fe))
547 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
549 if ( &(*fe) == &(*ii->m_frontend) )
552 decremented_cached_channel_fe_usecount = &ii->m_inuse;
561 decremented_cached_channel_fe_usecount=NULL;
563 ePtr<iDVBFrontendParameters> feparm;
567 eDebug("no channel list set!");
572 if (m_list->getChannelFrontendData(channelid, feparm))
574 eDebug("channel not found!");
579 ret = canAllocateFrontend(feparm);
582 if (decremented_fe_usecount)
583 ++(*decremented_fe_usecount);
584 if (decremented_cached_channel_fe_usecount)
585 ++(*decremented_cached_channel_fe_usecount);
590 DEFINE_REF(eDVBChannel);
592 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
594 m_frontend = frontend;
598 m_skipmode_n = m_skipmode_m = 0;
601 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
604 eDVBChannel::~eDVBChannel()
607 m_mgr->removeChannel(this);
612 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
614 int state, ourstate = 0;
616 /* if we are already in shutdown, don't change state. */
617 if (m_state == state_release)
620 if (fe->getState(state))
623 if (state == iDVBFrontend::stateLock)
625 eDebug("OURSTATE: ok");
627 } else if (state == iDVBFrontend::stateTuning)
629 eDebug("OURSTATE: tuning");
630 ourstate = state_tuning;
631 } else if (state == iDVBFrontend::stateLostLock)
633 /* on managed channels, we try to retune in order to re-acquire lock. */
636 eDebug("OURSTATE: lost lock, trying to retune");
637 ourstate = state_tuning;
638 m_frontend->get().tune(*m_feparm);
640 /* on unmanaged channels, we don't do this. the client will do this. */
642 eDebug("OURSTATE: lost lock, unavailable now.");
643 ourstate = state_unavailable;
645 } else if (state == iDVBFrontend::stateFailed)
647 eDebug("OURSTATE: failed");
648 ourstate = state_failed;
650 eFatal("state unknown");
652 if (ourstate != m_state)
655 m_stateChanged(this);
659 void eDVBChannel::pvrEvent(int event)
663 case eFilePushThread::evtEOF:
664 eDebug("eDVBChannel: End of file!");
665 m_event(this, evtEOF);
667 case eFilePushThread::evtUser: /* start */
669 m_event(this, evtSOF);
674 void eDVBChannel::cueSheetEvent(int event)
678 case eCueSheet::evtSeek:
680 flushPVR(m_cue->m_decoding_demux);
682 case eCueSheet::evtSkipmode:
685 eSingleLocker l(m_cue->m_lock);
686 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
687 if (m_cue->m_skipmode_ratio)
689 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
690 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
691 /* i agree that this might look a bit like black magic. */
692 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
693 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio;
695 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
697 if (abs(m_skipmode_m) < abs(m_skipmode_n))
699 eFatal("damn, something is wrong with this calculation");
700 m_skipmode_n = m_skipmode_m = 0;
705 eDebug("skipmode ratio is 0, normal play");
706 m_skipmode_n = m_skipmode_m = 0;
709 flushPVR(m_cue->m_decoding_demux);
712 case eCueSheet::evtSpanChanged:
713 eDebug("source span translation not yet supported");
714 // recheckCuesheetSpans();
719 /* remember, this gets called from another thread. */
720 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
722 unsigned int max = 10*1024*1024;
726 eDebug("no cue sheet. forcing normal play");
727 start = current_offset;
732 eSingleLocker l(m_cue->m_lock);
734 if (!m_cue->m_decoding_demux)
736 start = current_offset;
738 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
744 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
748 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
750 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
752 eDebug("reached SOF");
754 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
757 current_offset += m_skipmode_m;
759 while (!m_cue->m_seek_requests.empty())
761 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
762 m_cue->m_seek_requests.pop_front();
763 int relative = seek.first;
764 pts_t pts = seek.second;
766 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
774 /* we're using the decoder's timestamp here. this
775 won't work for radio (ouch). */
776 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
778 eDebug("seekTo: getCurrentPosition failed!");
787 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
789 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
790 current_offset = offset;
793 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
795 if ((current_offset >= i->first) && (current_offset < i->second))
797 start = current_offset;
798 size = i->second - current_offset;
801 eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
804 if (current_offset < i->first)
807 size = i->second - i->first;
815 start = current_offset;
817 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
824 void eDVBChannel::AddUse()
826 if (++m_use_count > 1 && m_state == state_last_instance)
829 m_stateChanged(this);
833 void eDVBChannel::ReleaseUse()
837 m_state = state_release;
838 m_stateChanged(this);
840 else if (m_use_count == 1)
842 m_state = state_last_instance;
843 m_stateChanged(this);
847 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
850 m_mgr->removeChannel(this);
857 eDebug("no frontend to tune!");
861 m_channel_id = channelid;
862 m_mgr->addChannel(channelid, this);
863 m_state = state_tuning;
864 /* if tuning fails, shutdown the channel immediately. */
866 res = m_frontend->get().tune(*feparm);
871 m_state = state_release;
872 m_stateChanged(this);
879 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
881 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
885 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
887 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
891 RESULT eDVBChannel::getState(int &state)
897 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
902 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
904 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
910 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
915 /* don't hold a reference to the decoding demux, we don't need it. */
921 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
923 frontend = &m_frontend->get();
930 RESULT eDVBChannel::playFile(const char *file)
935 m_pvr_thread->stop();
940 m_tstools.openFile(file);
942 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
943 THEN DO A REAL FIX HERE! */
945 /* (this codepath needs to be improved anyway.) */
946 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
947 if (m_pvr_fd_dst < 0)
949 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
953 m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
954 if (m_pvr_fd_src < 0)
956 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
962 m_stateChanged(this);
964 m_pvr_thread = new eFilePushThread();
965 m_pvr_thread->enablePVRCommit(1);
966 m_pvr_thread->setScatterGather(this);
968 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
969 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
974 void eDVBChannel::stopFile()
978 m_pvr_thread->stop();
979 ::close(m_pvr_fd_src);
980 ::close(m_pvr_fd_dst);
986 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
988 m_conn_cueSheetEvent = 0;
991 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
994 RESULT eDVBChannel::getLength(pts_t &len)
996 return m_tstools.calcLen(len);
999 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1001 if (!decoding_demux)
1005 /* getPTS for offset 0 is cached, so it doesn't harm. */
1006 int r = m_tstools.getPTS(begin, pos);
1009 eDebug("tstools getpts(0) failed!");
1015 /* TODO: this is a gross hack. */
1016 r = decoding_demux->getSTC(now, mode ? 128 : 0);
1020 eDebug("demux getSTC failed");
1024 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
1025 /* when we are less than 10 seconds before the start, return 0. */
1026 /* (we're just waiting for the timespam to start) */
1027 if ((now < pos) && ((pos - now) < 90000 * 10))
1033 if (now < pos) /* wrap around */
1034 pos = now + ((pts_t)1)<<33 - pos;
1041 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1043 /* when seeking, we have to ensure that all buffers are flushed.
1044 there are basically 3 buffers:
1045 a.) the filepush's internal buffer
1046 b.) the PVR buffer (before demux)
1047 c.) the ratebuffer (after demux)
1049 it's important to clear them in the correct order, otherwise
1050 the ratebuffer (for example) would immediately refill from
1051 the not-yet-flushed PVR buffer.
1054 m_pvr_thread->pause();
1055 /* flush internal filepush buffer */
1056 m_pvr_thread->flush();
1057 /* HACK: flush PVR buffer */
1058 ::ioctl(m_pvr_fd_dst, 0);
1060 /* flush ratebuffers (video, audio) */
1062 decoding_demux->flush();
1064 /* demux will also flush all decoder.. */
1065 /* resume will re-query the SG */
1066 m_pvr_thread->resume();
1069 DEFINE_REF(eCueSheet);
1071 eCueSheet::eCueSheet()
1073 m_skipmode_ratio = 0;
1076 void eCueSheet::seekTo(int relative, const pts_t &pts)
1079 eSingleLock l(m_lock);
1080 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1085 void eCueSheet::clear()
1087 eSingleLock l(m_lock);
1091 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1094 eSingleLock l(m_lock);
1095 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1097 m_event(evtSpanChanged);
1100 void eCueSheet::setSkipmode(const pts_t &ratio)
1103 eSingleLock l(m_lock);
1104 m_skipmode_ratio = ratio;
1106 m_event(evtSkipmode);
1109 void eCueSheet::setDecodingDemux(iDVBDemux *demux)
1111 m_decoding_demux = demux;
1114 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1116 connection = new eConnection(this, m_event.connect(event));