rewrite wrap around
[vuplus_dvbapp] / lib / dvb / dvb.cpp
index 601e627..ad865c0 100644 (file)
@@ -43,6 +43,7 @@ DEFINE_REF(eDVBResourceManager);
 eDVBResourceManager *eDVBResourceManager::instance;
 
 eDVBResourceManager::eDVBResourceManager()
+       :m_releaseCachedChannelTimer(eApp)
 {
        avail = 1;
        busy = 0;
@@ -63,6 +64,8 @@ eDVBResourceManager::eDVBResourceManager()
        
        eDebug("found %d adapter, %d frontends and %d demux", 
                m_adapter.size(), m_frontend.size(), m_demux.size());
+
+       CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
 }
 
 
@@ -307,7 +310,9 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse
                        channel = m_cached_channel;
                        return 0;
                }
+               m_cached_channel_state_changed_conn.disconnect();
                m_cached_channel=0;
+               m_releaseCachedChannelTimer.stop();
        }
 
 //     eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
@@ -355,16 +360,52 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse
                return errChidNotFound;
        }
        m_cached_channel = channel = ch;
+       m_cached_channel_state_changed_conn =
+               CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
 
        return 0;
 }
 
+void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
+{
+       int state=0;
+       chan->getState(state);
+       switch (state)
+       {
+               case iDVBChannel::state_release:
+               case iDVBChannel::state_ok:
+               {
+                       eDebug("stop release channel timer");
+                       m_releaseCachedChannelTimer.stop();
+                       break;
+               }
+               case iDVBChannel::state_last_instance:
+               {
+                       eDebug("start release channel timer");
+                       m_releaseCachedChannelTimer.start(3000, true);
+                       break;
+               }
+               default: // ignore all other events
+                       break;
+       }
+}
+
+void eDVBResourceManager::releaseCachedChannel()
+{
+       eDebug("release cached channel (timer timeout)");
+       m_cached_channel=0;
+}
+
 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
 {
        ePtr<eDVBAllocatedFrontend> fe;
 
        if (m_cached_channel)
+       {
+               m_cached_channel_state_changed_conn.disconnect();
                m_cached_channel=0;
+               m_releaseCachedChannelTimer.stop();
+       }
 
        if (allocateFrontendByIndex(fe, frontend_index))
                return errNoFrontend;
@@ -381,9 +422,6 @@ RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
 {
        ePtr<eDVBAllocatedDemux> demux;
 
-       if (m_cached_channel)
-               m_cached_channel=0;
-
        eDVBChannel *ch;
        ch = new eDVBChannel(this, 0);
        
@@ -780,7 +818,11 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off
 
 void eDVBChannel::AddUse()
 {
-       ++m_use_count;
+       if (++m_use_count > 1 && m_state == state_last_instance)
+       {
+               m_state = state_ok;
+               m_stateChanged(this);
+       }
 }
 
 void eDVBChannel::ReleaseUse()
@@ -790,6 +832,11 @@ void eDVBChannel::ReleaseUse()
                m_state = state_release;
                m_stateChanged(this);
        }
+       else if (m_use_count == 1)
+       {
+               m_state = state_last_instance;
+               m_stateChanged(this);
+       }
 }
 
 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
@@ -979,7 +1026,7 @@ RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, in
        }
        
        if (now < pos) /* wrap around */
-               pos = now + ((pts_t)1)<<33 - pos;
+               pos = now + 0x200000000LL - pos;
        else
                pos = now - pos;