Page MenuHome

audio_sleep.patch

Authored By
Tom Edwards (artfunkel)
Nov 19 2013, 11:21 AM
Size
14 KB
Subscribers
None

audio_sleep.patch

diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index c3877c2..9fb7084 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -101,12 +101,17 @@ AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, A
m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
m_device(device)
{
+ createHandle();
+}
+
+void AUD_OpenALDevice::AUD_OpenALHandle::createHandle()
+{
AUD_DeviceSpecs specs = m_device->m_specs;
specs.specs = m_reader->getSpecs();
// OpenAL playback code
alGenBuffers(CYCLE_BUFFERS, m_buffers);
- if(alGetError() != AL_NO_ERROR)
+ if (alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
try
@@ -115,12 +120,12 @@ AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, A
int length;
bool eos;
- for(int i = 0; i < CYCLE_BUFFERS; i++)
+ for (int i = 0; i < CYCLE_BUFFERS; i++)
{
length = m_device->m_buffersize;
- reader->read(length, eos, m_device->m_buffer.getBuffer());
+ m_reader->read(length, eos, m_device->m_buffer.getBuffer());
- if(length == 0)
+ if (length == 0)
{
// AUD_XXX: TODO: don't fill all buffers and enqueue them later
length = 1;
@@ -128,29 +133,29 @@ AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, A
}
alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
- length * AUD_DEVICE_SAMPLE_SIZE(specs),
- specs.rate);
- if(alGetError() != AL_NO_ERROR)
+ length * AUD_DEVICE_SAMPLE_SIZE(specs),
+ specs.rate);
+ if (alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
}
alGenSources(1, &m_source);
- if(alGetError() != AL_NO_ERROR)
+ if (alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
try
{
alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
- if(alGetError() != AL_NO_ERROR)
+ if (alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL, queue_error);
}
- catch(AUD_Exception&)
+ catch (AUD_Exception&)
{
alDeleteSources(1, &m_source);
throw;
}
}
- catch(AUD_Exception&)
+ catch (AUD_Exception&)
{
alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
throw;
@@ -877,6 +882,8 @@ void AUD_OpenALDevice::start(bool join)
pthread_attr_destroy(&attr);
m_playing = true;
+ if (m_context == NULL)
+ createContext();
}
}
@@ -1010,6 +1017,7 @@ void AUD_OpenALDevice::updateStreams()
else
alSourcePlay(sound->m_source);
}
+ m_lastsoundtime = clock();
}
for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
@@ -1025,9 +1033,10 @@ void AUD_OpenALDevice::updateStreams()
}
// stop thread
- if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
+ if ((clock() - m_lastsoundtime > 1000 && m_playingSounds.empty()) || cerr != ALC_NO_ERROR)
{
m_playing = false;
+ destroyContext();
unlock();
pthread_exit(NULL);
}
@@ -1048,11 +1057,11 @@ void AUD_OpenALDevice::updateStreams()
static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
-AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
+AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) : m_specs(specs), m_buffersize(buffersize)
{
// cannot determine how many channels or which format OpenAL uses, but
// it at least is able to play 16 bit stereo audio
- specs.format = AUD_FORMAT_S16;
+ m_specs.format = AUD_FORMAT_S16;
#if 0
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
@@ -1073,33 +1082,24 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
if(!m_device)
AUD_THROW(AUD_ERROR_OPENAL, open_error);
- // at least try to set the frequency
- ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
- ALCint* attributes = attribs;
- if(specs.rate == AUD_RATE_INVALID)
- attributes = NULL;
-
- m_context = alcCreateContext(m_device, attributes);
- alcMakeContextCurrent(m_context);
+ createContext();
- alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
+ alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*) &m_specs.rate);
// check for specific formats and channel counts to be played back
- if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
- specs.format = AUD_FORMAT_FLOAT32;
+ if (alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
+ m_specs.format = AUD_FORMAT_FLOAT32;
m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
- if((!m_useMC && specs.channels > AUD_CHANNELS_STEREO) ||
- specs.channels == AUD_CHANNELS_STEREO_LFE ||
- specs.channels == AUD_CHANNELS_SURROUND5)
- specs.channels = AUD_CHANNELS_STEREO;
+ if ((!m_useMC && m_specs.channels > AUD_CHANNELS_STEREO) ||
+ m_specs.channels == AUD_CHANNELS_STEREO_LFE ||
+ m_specs.channels == AUD_CHANNELS_SURROUND5)
+ m_specs.channels = AUD_CHANNELS_STEREO;
alGetError();
alcGetError(m_device);
- m_specs = specs;
- m_buffersize = buffersize;
m_playing = false;
// m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
@@ -1113,6 +1113,8 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
pthread_mutexattr_destroy(&attr);
start(false);
+
+ destroyContext();
}
AUD_OpenALDevice::~AUD_OpenALDevice()
@@ -1144,13 +1146,33 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
//delete m_bufferedFactories;
// quit OpenAL
- alcMakeContextCurrent(NULL);
- alcDestroyContext(m_context);
+ destroyContext();
alcCloseDevice(m_device);
pthread_mutex_destroy(&m_mutex);
}
+void AUD_OpenALDevice::createContext()
+{
+ ALCint attribs[] = { ALC_FREQUENCY, (ALCint) m_specs.rate, 0 };
+
+ m_context = alcCreateContext(m_device, m_specs.rate == AUD_RATE_INVALID ? NULL : attribs );
+ alcMakeContextCurrent(m_context);
+
+ AUD_HandleIterator it;
+ for (it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
+ (*it)->createHandle();
+ for (it = m_pausedSounds.begin(); it != m_pausedSounds.end(); it++)
+ (*it)->createHandle();
+}
+
+void AUD_OpenALDevice::destroyContext()
+{
+ alcMakeContextCurrent(NULL);
+ alcDestroyContext(m_context);
+ m_context = 0;
+}
+
AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
{
return m_specs;
@@ -1249,6 +1271,9 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep)
{
+ if (m_context == NULL)
+ createContext();
+
AUD_Specs specs = reader->getSpecs();
// check format
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
index f0e4782..c77f7bf 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
@@ -110,6 +110,7 @@ private:
AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep);
virtual ~AUD_OpenALHandle() {}
+ virtual void createHandle();
virtual bool pause();
virtual bool resume();
virtual bool stop();
@@ -204,6 +205,8 @@ private:
*/
bool m_playing;
+ clock_t m_lastsoundtime;
+
/**
* Buffer size.
*/
@@ -232,6 +235,14 @@ private:
* \return Whether the format is valid or not.
*/
bool getFormat(ALenum &format, AUD_Specs specs);
+
+ /*
+ * Dynamic OpenAL context management. Having a context
+ * open permanently causes Windows audio drivers to block
+ * the OS automatically entering sleep mode.
+ */
+ void createContext();
+ void destroyContext();
// hide copy constructor and operator=
AUD_OpenALDevice(const AUD_OpenALDevice&);
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp
index 0be8db9..784b171 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.cpp
+++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp
@@ -51,43 +51,54 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize)
specs.rate = AUD_RATE_44100;
m_specs = specs;
+ m_buffersize = buffersize;
+}
+void AUD_SDLDevice::create()
+{
+ lock();
SDL_AudioSpec format, obtained;
format.freq = m_specs.rate;
- if(m_specs.format == AUD_FORMAT_U8)
+ if (m_specs.format == AUD_FORMAT_U8)
format.format = AUDIO_U8;
else
format.format = AUDIO_S16SYS;
format.channels = m_specs.channels;
- format.samples = buffersize;
+ format.samples = m_buffersize;
format.callback = AUD_SDLDevice::SDL_mix;
format.userdata = this;
- if(SDL_OpenAudio(&format, &obtained) != 0)
+ if (SDL_OpenAudio(&format, &obtained) != 0)
AUD_THROW(AUD_ERROR_SDL, open_error);
- m_specs.rate = (AUD_SampleRate)obtained.freq;
- m_specs.channels = (AUD_Channels)obtained.channels;
- if(obtained.format == AUDIO_U8)
+ m_specs.rate = (AUD_SampleRate) obtained.freq;
+ m_specs.channels = (AUD_Channels) obtained.channels;
+ if (obtained.format == AUDIO_U8)
m_specs.format = AUD_FORMAT_U8;
- else if(obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
+ else if (obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
m_specs.format = AUD_FORMAT_S16;
else
{
SDL_CloseAudio();
AUD_THROW(AUD_ERROR_SDL, format_error);
}
+ unlock();
- create();
-}
+ AUD_SoftwareDevice::create();
+};
-AUD_SDLDevice::~AUD_SDLDevice()
+void AUD_SDLDevice::destroy()
{
lock();
SDL_CloseAudio();
unlock();
+ AUD_SoftwareDevice::destroy();
+};
+
+AUD_SDLDevice::~AUD_SDLDevice()
+{
destroy();
}
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h
index 266edd0..692ea91 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.h
+++ b/intern/audaspace/SDL/AUD_SDLDevice.h
@@ -48,6 +48,12 @@ private:
*/
static void SDL_mix(void *data, Uint8* buffer, int length);
+ virtual void create();
+ virtual void destroy();
+ virtual void suspend() { destroy(); }
+
+ int m_buffersize;
+
// hide copy constructor and operator=
AUD_SDLDevice(const AUD_SDLDevice&);
AUD_SDLDevice& operator=(const AUD_SDLDevice&);
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index 7bf59cd..9309939 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -265,6 +265,9 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume()
{
AUD_MutexLock lock(*m_device);
+ if (m_device->m_created == false)
+ m_device->create();
+
if(m_status == AUD_STATUS_PAUSED)
{
for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
@@ -698,6 +701,50 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeVolumeOuter(float volume)
/**************************** IDevice Code ************************************/
/******************************************************************************/
+AUD_SoftwareDevice::AUD_SoftwareDevice()
+{
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&m_mutex, &attr);
+
+ pthread_mutexattr_destroy(&attr);
+
+ m_created = false;
+}
+
+AUD_SoftwareDevice::~AUD_SoftwareDevice()
+{
+ pthread_mutex_destroy(&m_mutex);
+ destroy();
+}
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+void *AUD_SoftwareDevice::runSuspendThread(void *device)
+{
+ AUD_SoftwareDevice* dev = (AUD_SoftwareDevice*) device;
+ while (1)
+ {
+ if (clock() > dev->m_soundEndTime)
+ {
+ if (dev->m_created) dev->suspend();
+ return NULL;
+ }
+
+#ifdef WIN32
+ Sleep(20);
+#else
+ usleep(20000);
+#endif
+ }
+}
+
void AUD_SoftwareDevice::create()
{
m_playback = false;
@@ -709,27 +756,33 @@ void AUD_SoftwareDevice::create()
m_flags = 0;
m_quality = false;
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_mutex_init(&m_mutex, &attr);
+ pthread_create(&m_thread, &attr, runSuspendThread, this);
- pthread_mutexattr_destroy(&attr);
+ pthread_attr_destroy(&attr);
+
+ m_created = true;
+ m_soundEndTime = clock() + 100; // 100ms grace to actually mix something
}
void AUD_SoftwareDevice::destroy()
{
- if(m_playback)
+ if (!m_created) return;
+
+ if (m_playback)
playing(m_playback = false);
- while(!m_playingSounds.empty())
+ while (!m_playingSounds.empty())
m_playingSounds.front()->stop();
- while(!m_pausedSounds.empty())
+ while (!m_pausedSounds.empty())
m_pausedSounds.front()->stop();
- pthread_mutex_destroy(&m_mutex);
+ m_created = false;
+ pthread_join(m_thread, NULL);
}
void AUD_SoftwareDevice::mix(data_t* buffer, int length)
@@ -788,6 +841,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
}
m_mixer->mix(buf, pos, len, sound->m_volume);
+ m_soundEndTime = clock() + len;
// in case the end of the sound is reached
if(eos && !sound->m_loopcount)
@@ -846,6 +900,8 @@ AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
boost::shared_ptr<AUD_IHandle> AUD_SoftwareDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep)
{
+ if (m_created == false)
+ create();
// prepare the reader
// pitch
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index 3c8c1e4..7a4817a 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -210,6 +210,9 @@ protected:
typedef std::list<boost::shared_ptr<AUD_SoftwareHandle> >::iterator AUD_HandleIterator;
+ AUD_SoftwareDevice();
+ ~AUD_SoftwareDevice();
+
/**
* The specification of the device.
*/
@@ -228,12 +231,18 @@ protected:
/**
* Initializes member variables.
*/
- void create();
+ virtual void create();
/**
* Uninitializes member variables.
*/
- void destroy();
+ virtual void destroy();
+
+ /**
+ * Suspends audio output. Some APIs keep a stream active
+ * even when silent, messing with system standby.
+ */
+ virtual void suspend() {}
/**
* Mixes the next samples into the buffer.
@@ -254,6 +263,16 @@ protected:
*/
void setSpecs(AUD_Specs specs);
+ /**
+ * Whether the audio output stream is currently running.
+ */
+ bool m_created;
+
+ /*
+ * The clock() time at which all audio will have ended.
+ */
+ clock_t m_soundEndTime;
+
private:
/**
* The reading buffer.
@@ -276,6 +295,12 @@ private:
bool m_playback;
/**
+ * The suspend thread.
+ */
+ pthread_t m_thread;
+ static void* runSuspendThread(void* device);
+
+ /**
* The mutex for locking.
*/
pthread_mutex_t m_mutex;

File Metadata

Mime Type
text/x-diff
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
42/af/76669d1085eb122a3a039da19d58

Event Timeline