mirror of
https://github.com/love2d/love.git
synced 2026-08-19 20:19:42 +02:00
Increased robustness of audio module initialization (see issue #646.) Also changed Source:play to return a boolean indicating success.
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 *)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user