X-Git-Url: http://code.vuplus.com/gitweb/?a=blobdiff_plain;f=lib%2Fdvb%2Fdvb.cpp;h=ce096039c1c61477ffc028ab6bb24868bed67c89;hb=ba5ec76317a3bd96895506159b0d5bc1a1a6eecc;hp=17712dde154bb39d5beed4096db20dc79474fa8e;hpb=529d27d845bdc567ded0c43fe040ed674276936a;p=vuplus_dvbapp diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 17712dd..ce09603 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -96,6 +96,10 @@ eDVBResourceManager::eDVBResourceManager() m_boxtype = DM800; else if (!strncmp(tmp, "dm500hd\n", rd)) m_boxtype = DM500HD; + else if (!strncmp(tmp, "dm800se\n", rd)) + m_boxtype = DM800SE; + else if (!strncmp(tmp, "dm7020hd\n", rd)) + m_boxtype = DM7020HD; else { eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n"); if (m_demux.size() == 3) @@ -106,7 +110,7 @@ eDVBResourceManager::eDVBResourceManager() m_boxtype = DM8000; } - eDebug("found %d adapter, %d frontends(%d sim) and %d demux, boxtype %d", + eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d", m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype); eDVBCAService::registerChannelCallback(this); @@ -141,19 +145,20 @@ eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr) #endif if (stat(filename, &s)) break; - ePtr fe; + eDVBFrontend *fe; { int ok = 0; - fe = new eDVBFrontend(m_nr, num_fe, ok); + fe = new eDVBFrontend(m_nr, num_fe, ok, true); if (ok) - m_frontend.push_back(fe); + m_simulate_frontend.push_back(ePtr(fe)); } + { int ok = 0; - fe = new eDVBFrontend(m_nr, num_fe, ok, true); + fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe); if (ok) - m_simulate_frontend.push_back(fe); + m_frontend.push_back(ePtr(fe)); } ++num_fe; } @@ -318,27 +323,34 @@ PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list) PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list"); return NULL; } - if ((unsigned int)PyList_Size(list) != m_frontend.size()) + unsigned int assigned=0; + for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) { + int pos=0; + while (pos < PyList_Size(list)) { + ePyObject obj = PyList_GET_ITEM(list, pos++); + if (!i->m_frontend->setSlotInfo(obj)) + continue; + ++assigned; + break; + } + } + if (assigned != m_frontend.size()) { char blasel[256]; - sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist", - m_frontend.size(), PyList_Size(list)); + sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!", + m_frontend.size(), assigned); PyErr_SetString(PyExc_StandardError, blasel); return NULL; } - int pos=0; - for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) - { - ePyObject obj = PyList_GET_ITEM(list, pos++); - if (!i->m_frontend->setSlotInfo(obj)) - return NULL; - } - pos=0; for (eSmartPtrList::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i) { - ePyObject obj = PyList_GET_ITEM(list, pos++); - if (!i->m_frontend->setSlotInfo(obj)) - return NULL; + int pos=0; + while (pos < PyList_Size(list)) { + ePyObject obj = PyList_GET_ITEM(list, pos++); + if (!i->m_frontend->setSlotInfo(obj)) + continue; + break; + } } Py_RETURN_NONE; } @@ -455,7 +467,7 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr unused; - if (m_boxtype == DM800 || m_boxtype == DM500HD) // dm800 / 500hd + if (m_boxtype == DM800) // dm800 { cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux for (; i != m_demux.end(); ++i, ++n) @@ -511,32 +523,48 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtrm_adapter : m_adapter.begin(); /* look for a demux on the same adapter as the frontend, or the first adapter for dvr playback */ + int source = fe ? fe->m_frontend->getDVBID() : -1; cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux - for (; i != m_demux.end(); ++i, ++n) + if (!fe) { - if (fe) + /* + * For pvr playback, start with the last demux. + * On some hardware, we have less ca devices than demuxes, + * so we should try to leave the first demuxes for live tv, + * and start with the last for pvr playback + */ + i = m_demux.end(); + --i; + } + while (i != m_demux.end()) + { + if (i->m_adapter == adapter) { if (!i->m_inuse) { - if (!unused) - unused = i; + /* mark the first unused demux, we'll use that when we do not find a better match */ + if (!unused) unused = i; } - else if (i->m_adapter == fe->m_adapter && - i->m_demux->getSource() == fe->m_frontend->getDVBID()) + else { - demux = new eDVBAllocatedDemux(i); - return 0; + /* demux is in use, see if we can share it */ + if (source >= 0 && i->m_demux->getSource() == source) + { + demux = new eDVBAllocatedDemux(i); + return 0; + } } } - else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...) + if (fe) { - if (i->m_inuse) { - demux = new eDVBAllocatedDemux(i); - return 0; - } - unused = i; + ++i; + } + else + { + --i; } } } @@ -707,8 +735,7 @@ RESULT eDVBResourceManager::allocateRawChannel(eUsePtr &channel, in return 0; } - -RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr &channel) +RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr &channel) { ePtr demux; @@ -719,7 +746,18 @@ RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr &channel) m_releaseCachedChannelTimer->stop(); } - channel = new eDVBChannel(this, 0); + ePtr ch = new eDVBChannel(this, 0); + if (channelid) + { + /* + * user provided a channelid, with the clear intention for + * this channel to be registered at the resource manager. + * (allowing e.g. epgcache to be started) + */ + ePtr feparm; + ch->setChannel(channelid, feparm); + } + channel = ch; return 0; } @@ -1175,8 +1213,22 @@ void eDVBChannel::frontendStateChanged(iDVBFrontend*fe) } } else if (state == iDVBFrontend::stateFailed) { +#ifdef BUILD_VUPLUS /* ikseong */ + if (m_current_frontend_parameters) + { + eDebug("OURSTATE: lost lock, trying to retune"); + ourstate = state_tuning; + m_frontend->get().tune(*m_current_frontend_parameters); + } + else + { + eDebug("OURSTATE: failed"); + ourstate = state_failed; + } +#else eDebug("OURSTATE: failed"); ourstate = state_failed; +#endif } else eFatal("state unknown"); @@ -1479,7 +1531,7 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off size = max; else size = aligned_end - current_offset; - eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size); + eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size); return; } if (current_offset < aligned_start) @@ -1520,10 +1572,10 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off len = aligned_end - aligned_start; start = aligned_end - len; - eDebug("skipping to %llx, %d", start, len); + eDebug("skipping to %llx, %zd", start, len); } - eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end); + eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end); return; } } @@ -1539,7 +1591,7 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off { start = current_offset; size = max; - eDebug("NO CUESHEET. (%08llx, %d)", start, size); + eDebug("NO CUESHEET. (%08llx, %zd)", start, size); } else { start = current_offset; @@ -1579,14 +1631,15 @@ RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtraddChannel(channelid, this); + if (!m_frontend) { - eDebug("no frontend to tune!"); - return -ENODEV; + /* no frontend, no need to tune (must be a streamed service) */ + return 0; } - m_channel_id = channelid; - m_mgr->addChannel(channelid, this); m_state = state_tuning; /* if tuning fails, shutdown the channel immediately. */ int res; @@ -1657,6 +1710,18 @@ void eDVBChannel::SDTready(int result) m_SDT = 0; } +int eDVBChannel::reserveDemux() +{ + ePtr dmx; + if (!getDemux(dmx, 0)) + { + uint8_t id; + if (!dmx->getCADemuxID(id)) + return id; + } + return -1; +} + RESULT eDVBChannel::requestTsidOnid(ePyObject callback) { if (PyCallable_Check(callback)) @@ -1685,6 +1750,12 @@ RESULT eDVBChannel::getDemux(ePtr &demux, int cap) { ePtr &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux; + if (m_frontend == NULL) + { + /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */ + our_demux = m_decoder_demux ? m_decoder_demux : m_demux; + } + if (!our_demux) { demux = 0; @@ -1731,6 +1802,20 @@ RESULT eDVBChannel::getCurrentFrontendParameters(ePtr &p RESULT eDVBChannel::playFile(const char *file) { + eRawFile *f = new eRawFile(); + ePtr source = f; + + if (f->open(file) < 0) + { + eDebug("can't open PVR file %s (%m)", file); + return -ENOENT; + } + + return playSource(source, file); +} + +RESULT eDVBChannel::playSource(ePtr &source, const char *streaminfo_file) +{ ASSERT(!m_frontend); if (m_pvr_thread) { @@ -1739,7 +1824,13 @@ RESULT eDVBChannel::playFile(const char *file) m_pvr_thread = 0; } - m_tstools.openFile(file); + if (!source->valid()) + { + eDebug("PVR source is not valid!"); + return -ENOENT; + } + + m_tstools.setSource(source, streaminfo_file); /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST, THEN DO A REAL FIX HERE! */ @@ -1749,32 +1840,39 @@ RESULT eDVBChannel::playFile(const char *file) /* (this codepath needs to be improved anyway.) */ #if HAVE_DVB_API_VERSION < 3 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY); -#else - m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY); -#endif if (m_pvr_fd_dst < 0) { - eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. + eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. return -ENODEV; } +#else + ePtr &demux = m_demux ? m_demux : m_decoder_demux; + if (demux) + { + m_pvr_fd_dst = demux->get().openDVR(O_WRONLY); + if (m_pvr_fd_dst < 0) + { + eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. + return -ENODEV; + } + } + else + { + eDebug("no demux allocated yet.. so its not possible to open the dvr device!!"); + return -ENODEV; + } +#endif } m_pvr_thread = new eDVBChannelFilePush(); m_pvr_thread->enablePVRCommit(1); - m_pvr_thread->setStreamMode(1); + /* If the source specifies a length, it's a file. If not, it's a stream */ + m_pvr_thread->setStreamMode(source->length() <= 0); m_pvr_thread->setScatterGather(this); m_event(this, evtPreStart); - if (m_pvr_thread->start(file, m_pvr_fd_dst)) - { - delete m_pvr_thread; - m_pvr_thread = 0; - ::close(m_pvr_fd_dst); - m_pvr_fd_dst = -1; - eDebug("can't open PVR file %s (%m)", file); - return -ENOENT; - } + m_pvr_thread->start(source, m_pvr_fd_dst); CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent); m_state = state_ok; @@ -1783,7 +1881,7 @@ RESULT eDVBChannel::playFile(const char *file) return 0; } -void eDVBChannel::stopFile() +void eDVBChannel::stopSource() { if (m_pvr_thread) { @@ -1793,6 +1891,13 @@ void eDVBChannel::stopFile() } if (m_pvr_fd_dst >= 0) ::close(m_pvr_fd_dst); + ePtr d; + m_tstools.setSource(d); +} + +void eDVBChannel::stopFile() +{ + stopSource(); } void eDVBChannel::setCueSheet(eCueSheet *cuesheet)