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 /* max can not exceed max(size_t). i->second - current_offset, however, can. */
840 if ((i->second - current_offset) > max)
843 size = i->second - current_offset;
844 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
847 if (current_offset < i->first)
849 /* ok, our current offset is in an 'out' zone. */
850 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
852 /* in normal playback, just start at the next zone. */
855 /* size is not 64bit! */
856 if ((i->second - i->first) > max)
859 size = i->second - i->first;
862 if (m_skipmode_m < 0)
864 eDebug("reached SOF");
867 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
871 /* when skipping reverse, however, choose the zone before. */
873 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
876 if ((i->second - i->first) > max)
879 len = i->second - i->first;
881 start = i->second - len;
882 eDebug("skipping to %llx, %d", start, len);
888 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
890 eDebug("reached SOF");
892 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
895 start = current_offset;
897 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
901 void eDVBChannel::AddUse()
903 if (++m_use_count > 1 && m_state == state_last_instance)
906 m_stateChanged(this);
910 void eDVBChannel::ReleaseUse()
914 m_state = state_release;
915 m_stateChanged(this);
917 else if (m_use_count == 1)
919 m_state = state_last_instance;
920 m_stateChanged(this);
924 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
927 m_mgr->removeChannel(this);
934 eDebug("no frontend to tune!");
938 m_channel_id = channelid;
939 m_mgr->addChannel(channelid, this);
940 m_state = state_tuning;
941 /* if tuning fails, shutdown the channel immediately. */
943 res = m_frontend->get().tune(*feparm);
944 m_current_frontend_parameters = feparm;
948 m_state = state_release;
949 m_stateChanged(this);
956 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
958 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
962 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
964 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
968 RESULT eDVBChannel::getState(int &state)
974 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
979 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
981 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
987 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
992 /* don't hold a reference to the decoding demux, we don't need it. */
998 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1003 frontend = &m_frontend->get();
1009 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1011 param = m_current_frontend_parameters;
1015 RESULT eDVBChannel::playFile(const char *file)
1017 ASSERT(!m_frontend);
1020 m_pvr_thread->stop();
1021 delete m_pvr_thread;
1025 m_tstools.openFile(file);
1027 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1028 THEN DO A REAL FIX HERE! */
1030 /* (this codepath needs to be improved anyway.) */
1031 #if HAVE_DVB_API_VERSION < 3
1032 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1034 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1036 if (m_pvr_fd_dst < 0)
1038 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1043 m_stateChanged(this);
1045 m_pvr_thread = new eFilePushThread();
1046 m_pvr_thread->enablePVRCommit(1);
1047 m_pvr_thread->setScatterGather(this);
1049 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1051 delete m_pvr_thread;
1053 eDebug("can't open PVR file %s (%m)", file);
1056 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1061 void eDVBChannel::stopFile()
1065 m_pvr_thread->stop();
1066 ::close(m_pvr_fd_dst);
1067 delete m_pvr_thread;
1072 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1074 m_conn_cueSheetEvent = 0;
1077 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1080 RESULT eDVBChannel::getLength(pts_t &len)
1082 return m_tstools.calcLen(len);
1085 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1087 if (!decoding_demux)
1094 if (mode == 0) /* demux */
1096 r = decoding_demux->getSTC(now, 0);
1099 eDebug("demux getSTC failed");
1103 now = pos; /* fixup supplied */
1105 off_t off = 0; /* TODO: fixme */
1106 r = m_tstools.fixupPTS(off, now);
1109 eDebug("fixup PTS failed");
1118 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1120 /* when seeking, we have to ensure that all buffers are flushed.
1121 there are basically 3 buffers:
1122 a.) the filepush's internal buffer
1123 b.) the PVR buffer (before demux)
1124 c.) the ratebuffer (after demux)
1126 it's important to clear them in the correct order, otherwise
1127 the ratebuffer (for example) would immediately refill from
1128 the not-yet-flushed PVR buffer.
1131 m_pvr_thread->pause();
1132 /* flush internal filepush buffer */
1133 m_pvr_thread->flush();
1134 /* HACK: flush PVR buffer */
1135 ::ioctl(m_pvr_fd_dst, 0);
1137 /* flush ratebuffers (video, audio) */
1139 decoding_demux->flush();
1141 /* demux will also flush all decoder.. */
1142 /* resume will re-query the SG */
1143 m_pvr_thread->resume();
1146 DEFINE_REF(eCueSheet);
1148 eCueSheet::eCueSheet()
1150 m_skipmode_ratio = 0;
1153 void eCueSheet::seekTo(int relative, const pts_t &pts)
1156 eSingleLock l(m_lock);
1157 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1162 void eCueSheet::clear()
1164 eSingleLock l(m_lock);
1168 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1171 eSingleLock l(m_lock);
1172 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1176 void eCueSheet::commitSpans()
1178 m_event(evtSpanChanged);
1181 void eCueSheet::setSkipmode(const pts_t &ratio)
1184 eSingleLock l(m_lock);
1185 m_skipmode_ratio = ratio;
1187 m_event(evtSkipmode);
1190 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1192 m_decoding_demux = demux;
1193 m_decoder = decoder;
1196 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1198 connection = new eConnection(this, m_event.connect(event));