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();
315 m_releaseCachedChannelTimer.stop();
318 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
319 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
321 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
322 if (i->m_channel_id == channelid)
324 // eDebug("found shared channel..");
325 channel = i->m_channel;
330 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
334 eDebug("no channel list set!");
338 ePtr<iDVBFrontendParameters> feparm;
339 if (m_list->getChannelFrontendData(channelid, feparm))
341 eDebug("channel not found!");
345 /* allocate a frontend. */
347 ePtr<eDVBAllocatedFrontend> fe;
349 if (allocateFrontend(fe, feparm))
350 return errNoFrontend;
353 ePtr<eDVBChannel> ch;
354 ch = new eDVBChannel(this, fe);
356 res = ch->setChannel(channelid, feparm);
360 return errChidNotFound;
362 m_cached_channel = channel = ch;
363 m_cached_channel_state_changed_conn =
364 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
369 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
372 chan->getState(state);
375 case iDVBChannel::state_release:
376 case iDVBChannel::state_ok:
378 eDebug("stop release channel timer");
379 m_releaseCachedChannelTimer.stop();
382 case iDVBChannel::state_last_instance:
384 eDebug("start release channel timer");
385 m_releaseCachedChannelTimer.start(3000, true);
388 default: // ignore all other events
393 void eDVBResourceManager::releaseCachedChannel()
395 eDebug("release cached channel (timer timeout)");
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();
407 m_releaseCachedChannelTimer.stop();
410 if (allocateFrontendByIndex(fe, frontend_index))
411 return errNoFrontend;
414 ch = new eDVBChannel(this, fe);
421 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
423 ePtr<eDVBAllocatedDemux> demux;
426 ch = new eDVBChannel(this, 0);
432 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
434 m_active_channels.push_back(active_channel(chid, ch));
435 /* emit */ m_channelAdded(ch);
439 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
442 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
444 if (i->m_channel == ch)
446 i = m_active_channels.erase(i);
457 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
459 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
463 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
465 ePtr<eDVBRegisteredFrontend> best;
468 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
471 int c = i->m_frontend->isCompatibleWith(feparm);
479 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
482 if (m_cached_channel)
484 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
485 if(channelid==cache_chan->getChannelID())
489 /* first, check if a channel is already existing. */
490 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
491 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
493 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
494 if (i->m_channel_id == channelid)
496 // eDebug("found shared channel..");
501 int *decremented_cached_channel_fe_usecount=NULL,
502 *decremented_fe_usecount=NULL;
504 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
506 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
507 if (i->m_channel_id == ignore)
509 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
510 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
512 ePtr<iDVBFrontend> fe;
513 if (!i->m_channel->getFrontend(fe))
515 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
517 if ( &(*fe) == &(*ii->m_frontend) )
520 decremented_fe_usecount = &ii->m_inuse;
521 if (channel == &(*m_cached_channel))
522 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
532 if (!decremented_cached_channel_fe_usecount)
534 if (m_cached_channel)
536 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
537 if (channel->getUseCount() == 1)
539 ePtr<iDVBFrontend> fe;
540 if (!channel->getFrontend(fe))
542 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
544 if ( &(*fe) == &(*ii->m_frontend) )
547 decremented_cached_channel_fe_usecount = &ii->m_inuse;
556 decremented_cached_channel_fe_usecount=NULL;
558 ePtr<iDVBFrontendParameters> feparm;
562 eDebug("no channel list set!");
567 if (m_list->getChannelFrontendData(channelid, feparm))
569 eDebug("channel not found!");
574 ret = canAllocateFrontend(feparm);
577 if (decremented_fe_usecount)
578 ++(*decremented_fe_usecount);
579 if (decremented_cached_channel_fe_usecount)
580 ++(*decremented_cached_channel_fe_usecount);
585 DEFINE_REF(eDVBChannel);
587 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
589 m_frontend = frontend;
593 m_skipmode_n = m_skipmode_m = 0;
596 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
599 eDVBChannel::~eDVBChannel()
602 m_mgr->removeChannel(this);
607 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
609 int state, ourstate = 0;
611 /* if we are already in shutdown, don't change state. */
612 if (m_state == state_release)
615 if (fe->getState(state))
618 if (state == iDVBFrontend::stateLock)
620 eDebug("OURSTATE: ok");
622 } else if (state == iDVBFrontend::stateTuning)
624 eDebug("OURSTATE: tuning");
625 ourstate = state_tuning;
626 } else if (state == iDVBFrontend::stateLostLock)
628 /* on managed channels, we try to retune in order to re-acquire lock. */
629 if (m_current_frontend_parameters)
631 eDebug("OURSTATE: lost lock, trying to retune");
632 ourstate = state_tuning;
633 m_frontend->get().tune(*m_current_frontend_parameters);
635 /* on unmanaged channels, we don't do this. the client will do this. */
637 eDebug("OURSTATE: lost lock, unavailable now.");
638 ourstate = state_unavailable;
640 } else if (state == iDVBFrontend::stateFailed)
642 eDebug("OURSTATE: failed");
643 ourstate = state_failed;
645 eFatal("state unknown");
647 if (ourstate != m_state)
650 m_stateChanged(this);
654 void eDVBChannel::pvrEvent(int event)
658 case eFilePushThread::evtEOF:
659 eDebug("eDVBChannel: End of file!");
660 m_event(this, evtEOF);
662 case eFilePushThread::evtUser: /* start */
664 m_event(this, evtSOF);
669 void eDVBChannel::cueSheetEvent(int event)
673 case eCueSheet::evtSeek:
675 flushPVR(m_cue->m_decoding_demux);
677 case eCueSheet::evtSkipmode:
680 eSingleLocker l(m_cue->m_lock);
681 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
682 if (m_cue->m_skipmode_ratio)
684 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
685 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
686 /* i agree that this might look a bit like black magic. */
687 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
688 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
690 if (m_cue->m_skipmode_ratio < 0)
691 m_skipmode_m -= m_skipmode_n;
693 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
695 if (abs(m_skipmode_m) < abs(m_skipmode_n))
697 eWarning("something is wrong with this calculation");
698 m_skipmode_n = m_skipmode_m = 0;
703 eDebug("skipmode ratio is 0, normal play");
704 m_skipmode_n = m_skipmode_m = 0;
707 flushPVR(m_cue->m_decoding_demux);
710 case eCueSheet::evtSpanChanged:
712 m_source_span.clear();
713 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
715 off_t offset_in, offset_out;
716 pts_t pts_in = i->first, pts_out = i->second;
717 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
719 eDebug("span translation failed.\n");
722 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
723 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
730 /* remember, this gets called from another thread. */
731 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
733 unsigned int max = 10*1024*1024;
737 eDebug("no cue sheet. forcing normal play");
738 start = current_offset;
743 eSingleLocker l(m_cue->m_lock);
745 if (!m_cue->m_decoding_demux)
747 start = current_offset;
749 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
755 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
759 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
761 current_offset += m_skipmode_m;
763 while (!m_cue->m_seek_requests.empty())
765 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
766 m_cue->m_seek_requests.pop_front();
767 int relative = seek.first;
768 pts_t pts = seek.second;
773 if (!m_cue->m_decoder)
775 eDebug("no decoder - can't seek relative");
778 if (m_cue->m_decoder->getPTS(0, now))
780 eDebug("decoder getPTS failed, can't seek relative");
783 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
785 eDebug("seekTo: getCurrentPosition failed!");
790 if (relative == 1) /* pts relative */
801 if (relative == 2) /* AP relative */
803 eDebug("AP relative seeking: %lld, at %lld", pts, now);
805 if (m_tstools.getNextAccessPoint(nextap, now, pts))
808 eDebug("AP relative seeking failed!");
811 eDebug("next ap is %llx\n", pts);
817 if (m_tstools.getOffset(offset, pts))
820 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
821 current_offset = offset;
824 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
826 if ((current_offset >= i->first) && (current_offset < i->second))
828 start = current_offset;
829 size = i->second - current_offset;
832 eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
835 if (current_offset < i->first)
837 /* ok, our current offset is in an 'out' zone. */
838 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
840 /* in normal playback, just start at the next zone. */
842 size = i->second - i->first;
846 if (m_skipmode_m < 0)
848 eDebug("reached SOF");
851 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
855 /* when skipping reverse, however, choose the zone before. */
857 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
858 size_t len = i->second - i->first;
861 start = i->second - max;
863 eDebug("skipping to %llx, %d", start, size);
869 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
871 eDebug("reached SOF");
873 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
876 start = current_offset;
878 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
882 void eDVBChannel::AddUse()
884 if (++m_use_count > 1 && m_state == state_last_instance)
887 m_stateChanged(this);
891 void eDVBChannel::ReleaseUse()
895 m_state = state_release;
896 m_stateChanged(this);
898 else if (m_use_count == 1)
900 m_state = state_last_instance;
901 m_stateChanged(this);
905 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
908 m_mgr->removeChannel(this);
915 eDebug("no frontend to tune!");
919 m_channel_id = channelid;
920 m_mgr->addChannel(channelid, this);
921 m_state = state_tuning;
922 /* if tuning fails, shutdown the channel immediately. */
924 res = m_frontend->get().tune(*feparm);
925 m_current_frontend_parameters = feparm;
929 m_state = state_release;
930 m_stateChanged(this);
937 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
939 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
943 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
945 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
949 RESULT eDVBChannel::getState(int &state)
955 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
960 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
962 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
968 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
973 /* don't hold a reference to the decoding demux, we don't need it. */
979 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
981 frontend = &m_frontend->get();
987 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
989 param = m_current_frontend_parameters;
993 RESULT eDVBChannel::playFile(const char *file)
998 m_pvr_thread->stop();
1003 m_tstools.openFile(file);
1005 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1006 THEN DO A REAL FIX HERE! */
1008 /* (this codepath needs to be improved anyway.) */
1009 #if HAVE_DVB_API_VERSION < 3
1010 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1012 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1014 if (m_pvr_fd_dst < 0)
1016 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1021 m_stateChanged(this);
1023 m_pvr_thread = new eFilePushThread();
1024 m_pvr_thread->enablePVRCommit(1);
1025 m_pvr_thread->setScatterGather(this);
1027 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1029 delete m_pvr_thread;
1031 eDebug("can't open PVR file %s (%m)", file);
1034 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1039 void eDVBChannel::stopFile()
1043 m_pvr_thread->stop();
1044 ::close(m_pvr_fd_dst);
1045 delete m_pvr_thread;
1050 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1052 m_conn_cueSheetEvent = 0;
1055 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1058 RESULT eDVBChannel::getLength(pts_t &len)
1060 return m_tstools.calcLen(len);
1063 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1065 if (!decoding_demux)
1072 if (mode == 0) /* demux */
1074 r = decoding_demux->getSTC(now, 0);
1077 eDebug("demux getSTC failed");
1081 now = pos; /* fixup supplied */
1083 off_t off = 0; /* TODO: fixme */
1084 r = m_tstools.fixupPTS(off, now);
1087 eDebug("fixup PTS failed");
1096 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1098 /* when seeking, we have to ensure that all buffers are flushed.
1099 there are basically 3 buffers:
1100 a.) the filepush's internal buffer
1101 b.) the PVR buffer (before demux)
1102 c.) the ratebuffer (after demux)
1104 it's important to clear them in the correct order, otherwise
1105 the ratebuffer (for example) would immediately refill from
1106 the not-yet-flushed PVR buffer.
1109 m_pvr_thread->pause();
1110 /* flush internal filepush buffer */
1111 m_pvr_thread->flush();
1112 /* HACK: flush PVR buffer */
1113 ::ioctl(m_pvr_fd_dst, 0);
1115 /* flush ratebuffers (video, audio) */
1117 decoding_demux->flush();
1119 /* demux will also flush all decoder.. */
1120 /* resume will re-query the SG */
1121 m_pvr_thread->resume();
1124 DEFINE_REF(eCueSheet);
1126 eCueSheet::eCueSheet()
1128 m_skipmode_ratio = 0;
1131 void eCueSheet::seekTo(int relative, const pts_t &pts)
1134 eSingleLock l(m_lock);
1135 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1140 void eCueSheet::clear()
1142 eSingleLock l(m_lock);
1146 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1149 eSingleLock l(m_lock);
1150 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1154 void eCueSheet::commitSpans()
1156 m_event(evtSpanChanged);
1159 void eCueSheet::setSkipmode(const pts_t &ratio)
1162 eSingleLock l(m_lock);
1163 m_skipmode_ratio = ratio;
1165 m_event(evtSkipmode);
1168 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1170 m_decoding_demux = demux;
1171 m_decoder = decoder;
1174 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1176 connection = new eConnection(this, m_event.connect(event));