Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #1548 from DDDamian/SoftSuspendSink

[AE] Allow sink to decide how or if it can be suspended
  • Loading branch information...
commit f528cd3cb7a393dcca1b88f965b7838f1edad51e 2 parents cd5a8c3 + 2b41991
davilla davilla authored
78 xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
View
@@ -1017,34 +1017,8 @@ void CSoftAE::Run()
restart = true;
}
- if (m_playingStreams.empty() && m_playing_sounds.empty() && m_streams.empty() &&
- !m_softSuspend && !g_advancedSettings.m_streamSilence)
- {
- m_softSuspend = true;
- m_softSuspendTimer = XbmcThreads::SystemClockMillis() + 10000; //10.0 second delay for softSuspend
- }
-
- unsigned int curSystemClock = XbmcThreads::SystemClockMillis();
-
- /* idle while in Suspend() state until Resume() called */
- /* idle if nothing to play and user hasn't enabled */
- /* continuous streaming (silent stream) in as.xml */
- while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) &&
- m_running && !m_reOpen && !restart)
- {
- if (m_sink)
- {
- /* take the sink lock */
- CExclusiveLock sinkLock(m_sinkLock);
- //m_sink->Drain(); TODO: implement
- m_sink->Deinitialize();
- delete m_sink;
- m_sink = NULL;
- }
- if (!m_playingStreams.empty() || !m_playing_sounds.empty() || !m_sounds.empty())
- m_softSuspend = false;
- m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC);
- }
+ /* Handle idle or forced suspend */
+ ProcessSuspend();
/* if we are told to restart */
if (m_reOpen || restart || !m_sink)
@@ -1405,3 +1379,51 @@ inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream)
m_streamsPlaying = !m_playingStreams.empty();
}
+inline void CSoftAE::ProcessSuspend()
+{
+ bool sinkIsSuspended = false;
+
+ if (m_playingStreams.empty() && m_playing_sounds.empty() &&
+ !m_softSuspend && !g_advancedSettings.m_streamSilence)
+ {
+ m_softSuspend = true;
+ m_softSuspendTimer = XbmcThreads::SystemClockMillis() + 10000; //10.0 second delay for softSuspend
+ }
+
+ unsigned int curSystemClock = XbmcThreads::SystemClockMillis();
+
+ /* idle while in Suspend() state until Resume() called */
+ /* idle if nothing to play and user hasn't enabled */
+ /* continuous streaming (silent stream) in as.xml */
+ while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) &&
+ m_running && !m_reOpen)
+ {
+ if (m_sink && !sinkIsSuspended)
+ {
+ /* put the sink in Suspend mode */
+ CExclusiveLock sinkLock(m_sinkLock);
+ if (!m_sink->SoftSuspend())
+ {
+ sinkIsSuspended = false; //sink cannot be suspended
+ m_softSuspend = false; //break suspend loop
+ break;
+ }
+ else
+ sinkIsSuspended = true; //sink has suspended processing
+ sinkLock.Leave();
+ }
+
+ /* idle for platform-defined time */
+ m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC);
+
+ /* check if we need to resume for stream or sound */
+ if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty()))
+ {
+ m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit
+ sinkIsSuspended = false; //sink processing data
+ m_softSuspend = false; //break suspend loop
+ break;
+ }
+ }
+}
+
9 xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
View
@@ -120,6 +120,8 @@ class CSoftAE : public IThreadedAE
bool SetupEncoder(AEAudioFormat &format);
void Deinitialize();
+ inline void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */
+
inline void GetDeviceFriendlyName(std::string &device);
IAESink *GetSink(AEAudioFormat &desiredFormat, bool passthrough, std::string &device);
@@ -133,9 +135,10 @@ class CSoftAE : public IThreadedAE
bool m_stereoUpmix;
/* internal vars */
- bool m_running, m_reOpen, m_isSuspended;
- bool m_softSuspend; /* latches after last stream or sound played for timer below */
- unsigned int m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend */
+ bool m_running, m_reOpen;
+ bool m_isSuspended; /* engine suspended by external function to release audio context */
+ bool m_softSuspend; /* latches after last stream or sound played for timer below for idle */
+ unsigned int m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */
CEvent m_reOpenEvent;
CEvent m_wake;
12 xbmc/cores/AudioEngine/Interfaces/AESink.h
View
@@ -87,5 +87,17 @@ class IAESink
This method sets the volume control, volume ranges from 0.0 to 1.0.
*/
virtual void SetVolume(float volume) {};
+
+ /*
+ Requests sink to prepare itself for a suspend state
+ @return false if sink cannot be suspended
+ */
+ virtual bool SoftSuspend() {return false;};
+
+ /*
+ Notify sink to prepare to resume processing after suspend state
+ @return false if sink must be reinitialized
+ */
+ virtual bool SoftResume() {return false;};
};
6 xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
View
@@ -489,9 +489,6 @@ unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool ha
if (!m_pcm)
return 0;
- if (snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
- snd_pcm_start(m_pcm);
-
int ret;
ret = snd_pcm_avail(m_pcm);
@@ -520,6 +517,9 @@ unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool ha
}
}
+ if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
+ snd_pcm_start(m_pcm);
+
return ret;
}
24 xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
View
@@ -331,7 +331,8 @@ void CAESinkWASAPI::Deinitialize()
{
try
{
- m_pAudioClient->Stop();
+ m_pAudioClient->Stop(); //stop the audio output
+ m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
}
catch (...)
{
@@ -537,6 +538,27 @@ unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool
return NumFramesRequested;
}
+bool CAESinkWASAPI::SoftSuspend()
+{
+ /* Sink has been asked to suspend output - we release audio */
+ /* device as we are in exclusive mode and thus allow external */
+ /* audio sources to play. This requires us to reinitialize */
+ /* on resume. */
+
+ Deinitialize();
+
+ return true;
+}
+
+bool CAESinkWASAPI::SoftResume()
+{
+ /* Sink asked to resume output. To release audio device in */
+ /* exclusive mode we release the device context and therefore */
+ /* must reinitialize. Return false to force re-init by engine */
+
+ return false;
+}
+
void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
{
IMMDeviceEnumerator* pEnumerator = NULL;
3  xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h
View
@@ -43,6 +43,8 @@ class CAESinkWASAPI : public IAESink
virtual double GetCacheTime ();
virtual double GetCacheTotal ();
virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio);
+ virtual bool SoftSuspend ();
+ virtual bool SoftResume ();
static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList);
private:
bool InitializeExclusive(AEAudioFormat &format);
@@ -70,6 +72,7 @@ class CAESinkWASAPI : public IAESink
bool m_running;
bool m_initialized;
+ bool m_isSuspended; /* sink is in a suspended state - release audio device */
bool m_isDirty; /* sink output failed - needs re-init or new device */
unsigned int m_uiBufferLen; /* wasapi endpoint buffer size, in frames */
Please sign in to comment.
Something went wrong with that request. Please try again.