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 eDVBResourceManager::eDVBResourceManager()
56 :m_releaseCachedChannelTimer(eApp)
60 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
64 /* search available adapters... */
69 while (eDVBAdapterLinux::exist(num_adapter))
71 addAdapter(new eDVBAdapterLinux(num_adapter));
75 eDebug("found %d adapter, %d frontends and %d demux",
76 m_adapter.size(), m_frontend.size(), m_demux.size());
78 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
82 DEFINE_REF(eDVBAdapterLinux);
83 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
88 eDebug("scanning for frontends..");
93 #if HAVE_DVB_API_VERSION < 3
94 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
96 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
98 if (stat(filename, &s))
100 ePtr<eDVBFrontend> fe;
103 fe = new eDVBFrontend(m_nr, num_fe, ok);
105 m_frontend.push_back(fe);
115 #if HAVE_DVB_API_VERSION < 3
116 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
118 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
120 if (stat(filename, &s))
122 ePtr<eDVBDemux> demux;
124 demux = new eDVBDemux(m_nr, num_demux);
125 m_demux.push_back(demux);
131 int eDVBAdapterLinux::getNumDemux()
133 return m_demux.size();
136 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
138 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
139 while (nr && (i != m_demux.end()))
145 if (i != m_demux.end())
153 int eDVBAdapterLinux::getNumFrontends()
155 return m_frontend.size();
158 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
160 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
161 while (nr && (i != m_frontend.end()))
167 if (i != m_frontend.end())
175 int eDVBAdapterLinux::exist(int nr)
179 #if HAVE_DVB_API_VERSION < 3
180 sprintf(filename, "/dev/dvb/card%d", nr);
182 sprintf(filename, "/dev/dvb/adapter%d", nr);
184 if (!stat(filename, &s))
189 eDVBResourceManager::~eDVBResourceManager()
191 if (instance == this)
195 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
197 int num_fe = adapter->getNumFrontends();
198 int num_demux = adapter->getNumDemux();
200 m_adapter.push_back(adapter);
203 for (i=0; i<num_demux; ++i)
205 ePtr<eDVBDemux> demux;
206 if (!adapter->getDemux(demux, i))
207 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
210 for (i=0; i<num_fe; ++i)
212 ePtr<eDVBFrontend> frontend;
214 if (!adapter->getFrontend(frontend, i))
216 frontend->setSEC(m_sec);
217 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
222 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
224 ePtr<eDVBRegisteredFrontend> best;
227 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
230 int c = i->m_frontend->isCompatibleWith(feparm);
240 fe = new eDVBAllocatedFrontend(best);
249 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
251 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
252 if ((!nr) && !i->m_inuse)
254 fe = new eDVBAllocatedFrontend(i);
262 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
264 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
265 never use the first one unless we need a decoding demux. */
267 eDebug("allocate demux");
268 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
270 if (i == m_demux.end())
274 /* FIXME: hardware demux policy */
275 if (!(cap & iDVBChannel::capDecode))
278 for (; i != m_demux.end(); ++i, ++n)
279 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
281 if ((cap & iDVBChannel::capDecode) && n)
284 demux = new eDVBAllocatedDemux(i);
286 demux->get().setSourceFrontend(fe->m_frontend->getID());
288 demux->get().setSourcePVR(0);
291 eDebug("demux not found");
295 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
301 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
310 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
312 /* first, check if a channel is already existing. */
314 if (m_cached_channel)
316 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
317 if(channelid==cache_chan->getChannelID())
319 eDebug("use cached_channel");
320 channel = m_cached_channel;
323 m_cached_channel_state_changed_conn.disconnect();
325 m_releaseCachedChannelTimer.stop();
328 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
329 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
331 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
332 if (i->m_channel_id == channelid)
334 // eDebug("found shared channel..");
335 channel = i->m_channel;
340 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
344 eDebug("no channel list set!");
348 ePtr<iDVBFrontendParameters> feparm;
349 if (m_list->getChannelFrontendData(channelid, feparm))
351 eDebug("channel not found!");
355 /* allocate a frontend. */
357 ePtr<eDVBAllocatedFrontend> fe;
359 if (allocateFrontend(fe, feparm))
360 return errNoFrontend;
363 ePtr<eDVBChannel> ch;
364 ch = new eDVBChannel(this, fe);
366 res = ch->setChannel(channelid, feparm);
370 return errChidNotFound;
372 m_cached_channel = channel = ch;
373 m_cached_channel_state_changed_conn =
374 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
379 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
382 chan->getState(state);
385 case iDVBChannel::state_release:
386 case iDVBChannel::state_ok:
388 eDebug("stop release channel timer");
389 m_releaseCachedChannelTimer.stop();
392 case iDVBChannel::state_last_instance:
394 eDebug("start release channel timer");
395 m_releaseCachedChannelTimer.start(3000, true);
398 default: // ignore all other events
403 void eDVBResourceManager::releaseCachedChannel()
405 eDebug("release cached channel (timer timeout)");
409 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
411 ePtr<eDVBAllocatedFrontend> fe;
413 if (m_cached_channel)
415 m_cached_channel_state_changed_conn.disconnect();
417 m_releaseCachedChannelTimer.stop();
420 if (allocateFrontendByIndex(fe, frontend_index))
421 return errNoFrontend;
424 ch = new eDVBChannel(this, fe);
431 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
433 ePtr<eDVBAllocatedDemux> demux;
436 ch = new eDVBChannel(this, 0);
442 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
444 m_active_channels.push_back(active_channel(chid, ch));
445 /* emit */ m_channelAdded(ch);
449 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
452 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
454 if (i->m_channel == ch)
456 i = m_active_channels.erase(i);
467 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
469 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
473 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
475 ePtr<eDVBRegisteredFrontend> best;
478 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
481 int c = i->m_frontend->isCompatibleWith(feparm);
489 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
492 if (m_cached_channel)
494 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
495 if(channelid==cache_chan->getChannelID())
499 /* first, check if a channel is already existing. */
500 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
501 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
503 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
504 if (i->m_channel_id == channelid)
506 // eDebug("found shared channel..");
511 int *decremented_cached_channel_fe_usecount=NULL,
512 *decremented_fe_usecount=NULL;
514 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
516 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
517 if (i->m_channel_id == ignore)
519 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
520 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
522 ePtr<iDVBFrontend> fe;
523 if (!i->m_channel->getFrontend(fe))
525 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
527 if ( &(*fe) == &(*ii->m_frontend) )
530 decremented_fe_usecount = &ii->m_inuse;
531 if (channel == &(*m_cached_channel))
532 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
542 if (!decremented_cached_channel_fe_usecount)
544 if (m_cached_channel)
546 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
547 if (channel->getUseCount() == 1)
549 ePtr<iDVBFrontend> fe;
550 if (!channel->getFrontend(fe))
552 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
554 if ( &(*fe) == &(*ii->m_frontend) )
557 decremented_cached_channel_fe_usecount = &ii->m_inuse;
566 decremented_cached_channel_fe_usecount=NULL;
568 ePtr<iDVBFrontendParameters> feparm;
572 eDebug("no channel list set!");
577 if (m_list->getChannelFrontendData(channelid, feparm))
579 eDebug("channel not found!");
584 ret = canAllocateFrontend(feparm);
587 if (decremented_fe_usecount)
588 ++(*decremented_fe_usecount);
589 if (decremented_cached_channel_fe_usecount)
590 ++(*decremented_cached_channel_fe_usecount);
595 DEFINE_REF(eDVBChannel);
597 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
599 m_frontend = frontend;
603 m_skipmode_n = m_skipmode_m = 0;
606 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
609 eDVBChannel::~eDVBChannel()
612 m_mgr->removeChannel(this);
617 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
619 int state, ourstate = 0;
621 /* if we are already in shutdown, don't change state. */
622 if (m_state == state_release)
625 if (fe->getState(state))
628 if (state == iDVBFrontend::stateLock)
630 eDebug("OURSTATE: ok");
632 } else if (state == iDVBFrontend::stateTuning)
634 eDebug("OURSTATE: tuning");
635 ourstate = state_tuning;
636 } else if (state == iDVBFrontend::stateLostLock)
638 /* on managed channels, we try to retune in order to re-acquire lock. */
639 if (m_current_frontend_parameters)
641 eDebug("OURSTATE: lost lock, trying to retune");
642 ourstate = state_tuning;
643 m_frontend->get().tune(*m_current_frontend_parameters);
645 /* on unmanaged channels, we don't do this. the client will do this. */
647 eDebug("OURSTATE: lost lock, unavailable now.");
648 ourstate = state_unavailable;
650 } else if (state == iDVBFrontend::stateFailed)
652 eDebug("OURSTATE: failed");
653 ourstate = state_failed;
655 eFatal("state unknown");
657 if (ourstate != m_state)
660 m_stateChanged(this);
664 void eDVBChannel::pvrEvent(int event)
668 case eFilePushThread::evtEOF:
669 eDebug("eDVBChannel: End of file!");
670 m_event(this, evtEOF);
672 case eFilePushThread::evtUser: /* start */
674 m_event(this, evtSOF);
679 void eDVBChannel::cueSheetEvent(int event)
683 case eCueSheet::evtSeek:
685 flushPVR(m_cue->m_decoding_demux);
687 case eCueSheet::evtSkipmode:
690 eSingleLocker l(m_cue->m_lock);
691 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
692 if (m_cue->m_skipmode_ratio)
694 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
695 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
696 /* i agree that this might look a bit like black magic. */
697 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
698 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
700 if (m_cue->m_skipmode_ratio < 0)
701 m_skipmode_m -= m_skipmode_n;
703 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
705 if (abs(m_skipmode_m) < abs(m_skipmode_n))
707 eWarning("something is wrong with this calculation");
708 m_skipmode_n = m_skipmode_m = 0;
713 eDebug("skipmode ratio is 0, normal play");
714 m_skipmode_n = m_skipmode_m = 0;
717 flushPVR(m_cue->m_decoding_demux);
720 case eCueSheet::evtSpanChanged:
722 m_source_span.clear();
723 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
725 off_t offset_in, offset_out;
726 pts_t pts_in = i->first, pts_out = i->second;
727 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
729 eDebug("span translation failed.\n");
732 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
733 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
740 /* remember, this gets called from another thread. */
741 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
743 unsigned int max = 10*1024*1024;
747 eDebug("no cue sheet. forcing normal play");
748 start = current_offset;
753 eSingleLocker l(m_cue->m_lock);
755 if (!m_cue->m_decoding_demux)
757 start = current_offset;
759 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
765 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
769 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
771 current_offset += m_skipmode_m;
773 while (!m_cue->m_seek_requests.empty())
775 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
776 m_cue->m_seek_requests.pop_front();
777 int relative = seek.first;
778 pts_t pts = seek.second;
783 if (!m_cue->m_decoder)
785 eDebug("no decoder - can't seek relative");
788 if (m_cue->m_decoder->getPTS(0, now))
790 eDebug("decoder getPTS failed, can't seek relative");
793 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
795 eDebug("seekTo: getCurrentPosition failed!");
800 if (relative == 1) /* pts relative */
811 if (relative == 2) /* AP relative */
813 eDebug("AP relative seeking: %lld, at %lld", pts, now);
815 if (m_tstools.getNextAccessPoint(nextap, now, pts))
818 eDebug("AP relative seeking failed!");
821 eDebug("next ap is %llx\n", pts);
827 if (m_tstools.getOffset(offset, pts))
830 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
831 current_offset = offset;
834 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
836 if ((current_offset >= i->first) && (current_offset < i->second))
838 start = current_offset;
839 size = i->second - current_offset;
842 eDebug("HIT, %lld < %lld < %lld", i->first, current_offset, i->second);
845 if (current_offset < i->first)
847 /* ok, our current offset is in an 'out' zone. */
848 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
850 /* in normal playback, just start at the next zone. */
852 size = i->second - i->first;
856 if (m_skipmode_m < 0)
858 eDebug("reached SOF");
861 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
865 /* when skipping reverse, however, choose the zone before. */
867 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
868 size_t len = i->second - i->first;
871 start = i->second - max;
873 eDebug("skipping to %llx, %d", start, size);
879 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
881 eDebug("reached SOF");
883 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
886 start = current_offset;
888 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
892 void eDVBChannel::AddUse()
894 if (++m_use_count > 1 && m_state == state_last_instance)
897 m_stateChanged(this);
901 void eDVBChannel::ReleaseUse()
905 m_state = state_release;
906 m_stateChanged(this);
908 else if (m_use_count == 1)
910 m_state = state_last_instance;
911 m_stateChanged(this);
915 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
918 m_mgr->removeChannel(this);
925 eDebug("no frontend to tune!");
929 m_channel_id = channelid;
930 m_mgr->addChannel(channelid, this);
931 m_state = state_tuning;
932 /* if tuning fails, shutdown the channel immediately. */
934 res = m_frontend->get().tune(*feparm);
935 m_current_frontend_parameters = feparm;
939 m_state = state_release;
940 m_stateChanged(this);
947 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
949 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
953 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
955 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
959 RESULT eDVBChannel::getState(int &state)
965 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
970 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
972 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
978 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
983 /* don't hold a reference to the decoding demux, we don't need it. */
989 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
991 frontend = &m_frontend->get();
997 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
999 param = m_current_frontend_parameters;
1003 RESULT eDVBChannel::playFile(const char *file)
1005 ASSERT(!m_frontend);
1008 m_pvr_thread->stop();
1009 delete m_pvr_thread;
1013 m_tstools.openFile(file);
1015 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1016 THEN DO A REAL FIX HERE! */
1018 /* (this codepath needs to be improved anyway.) */
1019 #if HAVE_DVB_API_VERSION < 3
1020 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1022 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1024 if (m_pvr_fd_dst < 0)
1026 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1031 m_stateChanged(this);
1033 m_pvr_thread = new eFilePushThread();
1034 m_pvr_thread->enablePVRCommit(1);
1035 m_pvr_thread->setScatterGather(this);
1037 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1039 delete m_pvr_thread;
1041 eDebug("can't open PVR file %s (%m)", file);
1044 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1049 void eDVBChannel::stopFile()
1053 m_pvr_thread->stop();
1054 ::close(m_pvr_fd_dst);
1055 delete m_pvr_thread;
1060 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1062 m_conn_cueSheetEvent = 0;
1065 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1068 RESULT eDVBChannel::getLength(pts_t &len)
1070 return m_tstools.calcLen(len);
1073 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1075 if (!decoding_demux)
1082 if (mode == 0) /* demux */
1084 r = decoding_demux->getSTC(now, 0);
1087 eDebug("demux getSTC failed");
1091 now = pos; /* fixup supplied */
1093 off_t off = 0; /* TODO: fixme */
1094 r = m_tstools.fixupPTS(off, now);
1097 eDebug("fixup PTS failed");
1106 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1108 /* when seeking, we have to ensure that all buffers are flushed.
1109 there are basically 3 buffers:
1110 a.) the filepush's internal buffer
1111 b.) the PVR buffer (before demux)
1112 c.) the ratebuffer (after demux)
1114 it's important to clear them in the correct order, otherwise
1115 the ratebuffer (for example) would immediately refill from
1116 the not-yet-flushed PVR buffer.
1119 m_pvr_thread->pause();
1120 /* flush internal filepush buffer */
1121 m_pvr_thread->flush();
1122 /* HACK: flush PVR buffer */
1123 ::ioctl(m_pvr_fd_dst, 0);
1125 /* flush ratebuffers (video, audio) */
1127 decoding_demux->flush();
1129 /* demux will also flush all decoder.. */
1130 /* resume will re-query the SG */
1131 m_pvr_thread->resume();
1134 DEFINE_REF(eCueSheet);
1136 eCueSheet::eCueSheet()
1138 m_skipmode_ratio = 0;
1141 void eCueSheet::seekTo(int relative, const pts_t &pts)
1144 eSingleLock l(m_lock);
1145 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1150 void eCueSheet::clear()
1152 eSingleLock l(m_lock);
1156 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1159 eSingleLock l(m_lock);
1160 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1164 void eCueSheet::commitSpans()
1166 m_event(evtSpanChanged);
1169 void eCueSheet::setSkipmode(const pts_t &ratio)
1172 eSingleLock l(m_lock);
1173 m_skipmode_ratio = ratio;
1175 m_event(evtSkipmode);
1178 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1180 m_decoding_demux = demux;
1181 m_decoder = decoder;
1184 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1186 connection = new eConnection(this, m_event.connect(event));