Increased robustness of audio module initialization (see issue #646.) Also changed Source:play to return a boolean indicating success.

This commit is contained in:
Alex Szpakowski
2014-01-29 05:24:47 -04:00
parent 7ef0a6b576
commit a49c2a88c1
14 changed files with 83 additions and 47 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ public:
* Play the specified Source. * Play the specified Source.
* @param source The Source to play. * @param source The Source to play.
**/ **/
virtual void play(Source *source) = 0; virtual bool play(Source *source) = 0;
/** /**
* Stops playback on the specified source. * Stops playback on the specified source.
+1 -1
View File
@@ -53,7 +53,7 @@ public:
virtual Source *clone() = 0; virtual Source *clone() = 0;
virtual void play() = 0; virtual bool play() = 0;
virtual void stop() = 0; virtual void stop() = 0;
virtual void pause() = 0; virtual void pause() = 0;
virtual void resume() = 0; virtual void resume() = 0;
+2 -5
View File
@@ -61,12 +61,9 @@ int Audio::getMaxSources() const
return 0; return 0;
} }
void Audio::play(love::audio::Source *) bool Audio::play(love::audio::Source *)
{
}
void Audio::play()
{ {
return false;
} }
void Audio::stop(love::audio::Source *) void Audio::stop(love::audio::Source *)
+1 -2
View File
@@ -48,8 +48,7 @@ public:
love::audio::Source *newSource(love::sound::SoundData *soundData); love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const; int getSourceCount() const;
int getMaxSources() const; int getMaxSources() const;
void play(love::audio::Source *source); bool play(love::audio::Source *source);
void play();
void stop(love::audio::Source *source); void stop(love::audio::Source *source);
void stop(); void stop();
void pause(love::audio::Source *source); void pause(love::audio::Source *source);
+2 -1
View File
@@ -42,8 +42,9 @@ love::audio::Source *Source::clone()
return this; return this;
} }
void Source::play() bool Source::play()
{ {
return false;
} }
void Source::stop() void Source::stop()
+1 -1
View File
@@ -39,7 +39,7 @@ public:
virtual ~Source(); virtual ~Source();
virtual love::audio::Source *clone(); virtual love::audio::Source *clone();
virtual void play(); virtual bool play();
virtual void stop(); virtual void stop();
virtual void pause(); virtual void pause();
virtual void resume(); virtual void resume();
+28 -14
View File
@@ -69,22 +69,25 @@ void Audio::PoolThread::setFinish()
} }
Audio::Audio() Audio::Audio()
: distanceModel(DISTANCE_INVERSE_CLAMPED) : device(nullptr)
, capture(nullptr)
, context(nullptr)
, pool(nullptr)
, poolThread(nullptr)
, distanceModel(DISTANCE_INVERSE_CLAMPED)
{ {
// Passing zero for default device. // Passing null for default device.
device = alcOpenDevice(0); device = alcOpenDevice(nullptr);
if (device == 0) if (device == nullptr)
throw love::Exception("Could not open device."); throw love::Exception("Could not open device.");
context = alcCreateContext(device, 0); context = alcCreateContext(device, nullptr);
if (context == 0) if (context == nullptr)
throw love::Exception("Could not create context."); throw love::Exception("Could not create context.");
alcMakeContextCurrent(context); if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR)
if (alcGetError(device) != ALC_NO_ERROR)
throw love::Exception("Could not make context current."); throw love::Exception("Could not make context current.");
/*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); /*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
@@ -108,7 +111,18 @@ Audio::Audio()
}*/ }*/
// pool must be allocated after AL context. // pool must be allocated after AL context.
pool = new Pool(); try
{
pool = new Pool();
}
catch (love::Exception &)
{
alcMakeContextCurrent(nullptr);
alcDestroyContext(context);
//if (capture) alcCaptureCloseDevice(capture);
alcCloseDevice(device);
throw;
}
poolThread = new PoolThread(pool); poolThread = new PoolThread(pool);
poolThread->start(); poolThread->start();
@@ -122,7 +136,7 @@ Audio::~Audio()
delete poolThread; delete poolThread;
delete pool; delete pool;
alcMakeContextCurrent(0); alcMakeContextCurrent(nullptr);
alcDestroyContext(context); alcDestroyContext(context);
//if (capture) alcCaptureCloseDevice(capture); //if (capture) alcCaptureCloseDevice(capture);
alcCloseDevice(device); alcCloseDevice(device);
@@ -154,9 +168,9 @@ int Audio::getMaxSources() const
return pool->getMaxSources(); return pool->getMaxSources();
} }
void Audio::play(love::audio::Source *source) bool Audio::play(love::audio::Source *source)
{ {
source->play(); return source->play();
} }
void Audio::stop(love::audio::Source *source) void Audio::stop(love::audio::Source *source)
@@ -281,7 +295,7 @@ bool Audio::canRecord()
Audio::DistanceModel Audio::getDistanceModel() const Audio::DistanceModel Audio::getDistanceModel() const
{ {
return this->distanceModel; return distanceModel;
} }
void Audio::setDistanceModel(DistanceModel distanceModel) void Audio::setDistanceModel(DistanceModel distanceModel)
+1 -2
View File
@@ -67,8 +67,7 @@ public:
love::audio::Source *newSource(love::sound::SoundData *soundData); love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const; int getSourceCount() const;
int getMaxSources() const; int getMaxSources() const;
void play(love::audio::Source *source); bool play(love::audio::Source *source);
void play();
void stop(love::audio::Source *source); void stop(love::audio::Source *source);
void stop(); void stop();
void pause(love::audio::Source *source); void pause(love::audio::Source *source);
+30 -10
View File
@@ -30,23 +30,43 @@ namespace openal
{ {
Pool::Pool() Pool::Pool()
: sources()
, totalSources(0)
, mutex(nullptr)
{ {
// Clear errors.
alGetError();
// Generate sources. // Generate sources.
alGenSources(NUM_SOURCES, sources); for (int i = 0; i < MAX_SOURCES; i++)
{
alGenSources(1, &sources[i]);
// We might hit an implementation-dependent limit on the total number
// of sources before reaching MAX_SOURCES.
if (alGetError() != AL_NO_ERROR)
break;
totalSources++;
}
if (totalSources < 4)
throw love::Exception("Could not generate sources.");
// Create the mutex. // Create the mutex.
mutex = thread::newMutex(); mutex = thread::newMutex();
if (alGetError() != AL_NO_ERROR) ALboolean hasext = alIsExtensionPresent("AL_SOFT_direct_channels");
throw love::Exception("Could not generate sources.");
// Make all sources available initially. // Make all sources available initially.
for (int i = 0; i < NUM_SOURCES; i++) for (int i = 0; i < totalSources; i++)
{ {
#ifdef AL_DIRECT_CHANNELS_SOFT if (hasext)
// Bypassing virtualization of speakers for multi-channel sources in OpenAL Soft. {
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE); // Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
#endif alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
}
available.push(sources[i]); available.push(sources[i]);
} }
} }
@@ -58,7 +78,7 @@ Pool::~Pool()
delete mutex; delete mutex;
// Free all sources. // Free all sources.
alDeleteSources(NUM_SOURCES, sources); alDeleteSources(totalSources, sources);
} }
bool Pool::isAvailable() const bool Pool::isAvailable() const
@@ -113,7 +133,7 @@ int Pool::getSourceCount() const
int Pool::getMaxSources() const int Pool::getMaxSources() const
{ {
return NUM_SOURCES; return totalSources;
} }
bool Pool::play(Source *source, ALuint &out) bool Pool::play(Source *source, ALuint &out)
+8 -3
View File
@@ -36,6 +36,7 @@
#ifdef LOVE_MACOSX_USE_FRAMEWORKS #ifdef LOVE_MACOSX_USE_FRAMEWORKS
#include <OpenAL-Soft/alc.h> #include <OpenAL-Soft/alc.h>
#include <OpenAL-Soft/al.h> #include <OpenAL-Soft/al.h>
#include <OpenAL-Soft/alext.h>
#else #else
#include <AL/alc.h> #include <AL/alc.h>
#include <AL/al.h> #include <AL/al.h>
@@ -99,11 +100,15 @@ private:
bool findSource(Source *source, ALuint &out); bool findSource(Source *source, ALuint &out);
bool removeSource(Source *source); bool removeSource(Source *source);
// Number of OpenAL sources.
static const int NUM_SOURCES = 64; // Maximum possible number of OpenAL sources the pool attempts to generate.
static const int MAX_SOURCES = 64;
// OpenAL sources // OpenAL sources
ALuint sources[NUM_SOURCES]; ALuint sources[MAX_SOURCES];
// Total number of created sources in the pool.
int totalSources;
// A queue of available sources. // A queue of available sources.
std::queue<ALuint> available; std::queue<ALuint> available;
+3 -2
View File
@@ -165,15 +165,16 @@ love::audio::Source *Source::clone()
return new Source(*this); return new Source(*this);
} }
void Source::play() bool Source::play()
{ {
if (valid && paused) if (valid && paused)
{ {
pool->resume(this); pool->resume(this);
return; return true;
} }
valid = pool->play(this, source); valid = pool->play(this, source);
return valid;
} }
void Source::stop() void Source::stop()
+1 -1
View File
@@ -76,7 +76,7 @@ public:
virtual ~Source(); virtual ~Source();
virtual love::audio::Source *clone(); virtual love::audio::Source *clone();
virtual void play(); virtual bool play();
virtual void stop(); virtual void stop();
virtual void pause(); virtual void pause();
virtual void resume(); virtual void resume();
+2 -2
View File
@@ -75,8 +75,8 @@ int w_newSource(lua_State *L)
int w_play(lua_State *L) int w_play(lua_State *L)
{ {
Source *s = luax_checksource(L, 1); Source *s = luax_checksource(L, 1);
instance->play(s); luax_pushboolean(L, instance->play(s));
return 0; return 1;
} }
int w_stop(lua_State *L) int w_stop(lua_State *L)
+2 -2
View File
@@ -44,8 +44,8 @@ int w_Source_clone(lua_State *L)
int w_Source_play(lua_State *L) int w_Source_play(lua_State *L)
{ {
Source *t = luax_checksource(L, 1); Source *t = luax_checksource(L, 1);
t->play(); luax_pushboolean(L, t->play());
return 0; return 1;
} }
int w_Source_stop(lua_State *L) int w_Source_stop(lua_State *L)