diff --git a/src/modules/audio/Audio.h b/src/modules/audio/Audio.h index b7c192577..b43391dbe 100644 --- a/src/modules/audio/Audio.h +++ b/src/modules/audio/Audio.h @@ -88,7 +88,7 @@ public: * Play the specified Source. * @param source The Source to play. **/ - virtual void play(Source *source) = 0; + virtual bool play(Source *source) = 0; /** * Stops playback on the specified source. diff --git a/src/modules/audio/Source.h b/src/modules/audio/Source.h index b7a17d02d..43c5fafca 100644 --- a/src/modules/audio/Source.h +++ b/src/modules/audio/Source.h @@ -53,7 +53,7 @@ public: virtual Source *clone() = 0; - virtual void play() = 0; + virtual bool play() = 0; virtual void stop() = 0; virtual void pause() = 0; virtual void resume() = 0; diff --git a/src/modules/audio/null/Audio.cpp b/src/modules/audio/null/Audio.cpp index 2e5031ae1..6b6fd3f93 100644 --- a/src/modules/audio/null/Audio.cpp +++ b/src/modules/audio/null/Audio.cpp @@ -61,12 +61,9 @@ int Audio::getMaxSources() const return 0; } -void Audio::play(love::audio::Source *) -{ -} - -void Audio::play() +bool Audio::play(love::audio::Source *) { + return false; } void Audio::stop(love::audio::Source *) diff --git a/src/modules/audio/null/Audio.h b/src/modules/audio/null/Audio.h index 3f571da67..372f756c5 100644 --- a/src/modules/audio/null/Audio.h +++ b/src/modules/audio/null/Audio.h @@ -48,8 +48,7 @@ public: love::audio::Source *newSource(love::sound::SoundData *soundData); int getSourceCount() const; int getMaxSources() const; - void play(love::audio::Source *source); - void play(); + bool play(love::audio::Source *source); void stop(love::audio::Source *source); void stop(); void pause(love::audio::Source *source); diff --git a/src/modules/audio/null/Source.cpp b/src/modules/audio/null/Source.cpp index d343587f8..0fc043cc3 100644 --- a/src/modules/audio/null/Source.cpp +++ b/src/modules/audio/null/Source.cpp @@ -42,8 +42,9 @@ love::audio::Source *Source::clone() return this; } -void Source::play() +bool Source::play() { + return false; } void Source::stop() diff --git a/src/modules/audio/null/Source.h b/src/modules/audio/null/Source.h index 887b3ef56..326ff23d5 100644 --- a/src/modules/audio/null/Source.h +++ b/src/modules/audio/null/Source.h @@ -39,7 +39,7 @@ public: virtual ~Source(); virtual love::audio::Source *clone(); - virtual void play(); + virtual bool play(); virtual void stop(); virtual void pause(); virtual void resume(); diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp index 07ce2959d..c6af9be19 100644 --- a/src/modules/audio/openal/Audio.cpp +++ b/src/modules/audio/openal/Audio.cpp @@ -69,22 +69,25 @@ void Audio::PoolThread::setFinish() } 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. - device = alcOpenDevice(0); + // Passing null for default device. + device = alcOpenDevice(nullptr); - if (device == 0) + if (device == nullptr) 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."); - alcMakeContextCurrent(context); - - if (alcGetError(device) != ALC_NO_ERROR) + if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR) throw love::Exception("Could not make context current."); /*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); @@ -108,7 +111,18 @@ Audio::Audio() }*/ // 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->start(); @@ -122,7 +136,7 @@ Audio::~Audio() delete poolThread; delete pool; - alcMakeContextCurrent(0); + alcMakeContextCurrent(nullptr); alcDestroyContext(context); //if (capture) alcCaptureCloseDevice(capture); alcCloseDevice(device); @@ -154,9 +168,9 @@ int Audio::getMaxSources() const 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) @@ -281,7 +295,7 @@ bool Audio::canRecord() Audio::DistanceModel Audio::getDistanceModel() const { - return this->distanceModel; + return distanceModel; } void Audio::setDistanceModel(DistanceModel distanceModel) diff --git a/src/modules/audio/openal/Audio.h b/src/modules/audio/openal/Audio.h index a40494b2a..6e5f50696 100644 --- a/src/modules/audio/openal/Audio.h +++ b/src/modules/audio/openal/Audio.h @@ -67,8 +67,7 @@ public: love::audio::Source *newSource(love::sound::SoundData *soundData); int getSourceCount() const; int getMaxSources() const; - void play(love::audio::Source *source); - void play(); + bool play(love::audio::Source *source); void stop(love::audio::Source *source); void stop(); void pause(love::audio::Source *source); diff --git a/src/modules/audio/openal/Pool.cpp b/src/modules/audio/openal/Pool.cpp index f3d74a91a..8fde3785b 100644 --- a/src/modules/audio/openal/Pool.cpp +++ b/src/modules/audio/openal/Pool.cpp @@ -30,23 +30,43 @@ namespace openal { Pool::Pool() + : sources() + , totalSources(0) + , mutex(nullptr) { + // Clear errors. + alGetError(); + // 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. mutex = thread::newMutex(); - if (alGetError() != AL_NO_ERROR) - throw love::Exception("Could not generate sources."); + ALboolean hasext = alIsExtensionPresent("AL_SOFT_direct_channels"); // 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 - // Bypassing virtualization of speakers for multi-channel sources in OpenAL Soft. - alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE); -#endif + if (hasext) + { + // Bypass virtualization of speakers for multi-channel sources in OpenAL Soft. + alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE); + } + available.push(sources[i]); } } @@ -58,7 +78,7 @@ Pool::~Pool() delete mutex; // Free all sources. - alDeleteSources(NUM_SOURCES, sources); + alDeleteSources(totalSources, sources); } bool Pool::isAvailable() const @@ -113,7 +133,7 @@ int Pool::getSourceCount() const int Pool::getMaxSources() const { - return NUM_SOURCES; + return totalSources; } bool Pool::play(Source *source, ALuint &out) diff --git a/src/modules/audio/openal/Pool.h b/src/modules/audio/openal/Pool.h index 46353e759..f0896ea97 100644 --- a/src/modules/audio/openal/Pool.h +++ b/src/modules/audio/openal/Pool.h @@ -36,6 +36,7 @@ #ifdef LOVE_MACOSX_USE_FRAMEWORKS #include #include +#include #else #include #include @@ -99,11 +100,15 @@ private: bool findSource(Source *source, ALuint &out); 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 - ALuint sources[NUM_SOURCES]; + ALuint sources[MAX_SOURCES]; + + // Total number of created sources in the pool. + int totalSources; // A queue of available sources. std::queue available; diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index 332eb336e..1ea4243aa 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -165,15 +165,16 @@ love::audio::Source *Source::clone() return new Source(*this); } -void Source::play() +bool Source::play() { if (valid && paused) { pool->resume(this); - return; + return true; } valid = pool->play(this, source); + return valid; } void Source::stop() diff --git a/src/modules/audio/openal/Source.h b/src/modules/audio/openal/Source.h index 9a1182d74..911b57978 100644 --- a/src/modules/audio/openal/Source.h +++ b/src/modules/audio/openal/Source.h @@ -76,7 +76,7 @@ public: virtual ~Source(); virtual love::audio::Source *clone(); - virtual void play(); + virtual bool play(); virtual void stop(); virtual void pause(); virtual void resume(); diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 4b8e39969..217c4f98e 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -75,8 +75,8 @@ int w_newSource(lua_State *L) int w_play(lua_State *L) { Source *s = luax_checksource(L, 1); - instance->play(s); - return 0; + luax_pushboolean(L, instance->play(s)); + return 1; } int w_stop(lua_State *L) diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp index d1f3e61a1..b6b152b2b 100644 --- a/src/modules/audio/wrap_Source.cpp +++ b/src/modules/audio/wrap_Source.cpp @@ -44,8 +44,8 @@ int w_Source_clone(lua_State *L) int w_Source_play(lua_State *L) { Source *t = luax_checksource(L, 1); - t->play(); - return 0; + luax_pushboolean(L, t->play()); + return 1; } int w_Source_stop(lua_State *L)