pull request feedback addressed

newQueueableSource added
isQueueable removed, getFreeBufferCount added
queueData renamed to queue; added 3 argument variant with (data, offset, length)
lightuserdata variant now requires offset (pointer, offset, length, samplerate, bitdepth, channels)
setLooping now throws exception if called on queueable source

--HG--
branch : minor
This commit is contained in:
rcoaxil
2016-10-13 04:40:41 +03:00
parent b1c842f186
commit b757a0534e
9 changed files with 128 additions and 88 deletions
+2 -2
View File
@@ -102,8 +102,8 @@ public:
virtual int getChannels() const = 0;
virtual bool isQueueable() const = 0;
virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0;
virtual int getFreeBufferCount() const = 0;
virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0;
virtual Type getType() const;
+3 -3
View File
@@ -217,12 +217,12 @@ int Source::getChannels() const
return 2;
}
bool Source::isQueueable() const
int Source::getFreeBufferCount() const
{
return false;
return 0;
}
bool Source::queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels)
bool Source::queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels)
{
return false;
}
+2 -2
View File
@@ -76,8 +76,8 @@ public:
virtual float getMaxDistance() const;
virtual int getChannels() const;
virtual bool isQueueable() const;
virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels);
virtual int getFreeBufferCount() const;
virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels);
private:
+2 -2
View File
@@ -283,10 +283,10 @@ double Pool::getDuration(Source *source, void *unit)
return source->getDurationAtomic(unit);
}
bool Pool::queueData(Source *source, void *data, ALsizei length)
bool Pool::queue(Source *source, void *data, ALsizei length)
{
thread::Lock lock(mutex);
return source->queueDataAtomic(data, length);
return source->queueAtomic(data, length);
}
ALuint Pool::findi(const Source *source) const
+1 -1
View File
@@ -91,7 +91,7 @@ public:
void seek(Source *source, float offset, void *unit);
float tell(Source *source, void *unit);
double getDuration(Source *source, void *unit);
bool queueData(Source *source, void *data, ALsizei length);
bool queue(Source *source, void *data, ALsizei length);
bool play(const std::vector<love::audio::Source*> &sources);
void stop(const std::vector<love::audio::Source*> &sources);
+36 -29
View File
@@ -80,18 +80,7 @@ class QueueTypeMismatchException : public love::Exception
public:
QueueTypeMismatchException()
: Exception("Only \"queue\" type sound Sources can be queued with sound data.")
{
}
};
class QueueNegativeLengthException : public love::Exception
{
public:
QueueNegativeLengthException()
: Exception("Data length cannot be negative.")
: Exception("Only queueable Sources can be queued with sound data.")
{
}
@@ -102,12 +91,24 @@ class QueueMalformedLengthException : public love::Exception
public:
QueueMalformedLengthException(int bytes)
: Exception("Data lenght must be a multiple of sample size (%d bytes).", bytes)
: Exception("Data length must be a multiple of sample size (%d bytes).", bytes)
{
}
};
class QueueLoopingException : public love::Exception
{
public:
QueueLoopingException()
: Exception("Queueable Sources can not be looped.")
{
}
};
StaticDataBuffer::StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
: size(size)
{
@@ -317,10 +318,10 @@ bool Source::isPlaying() const
}
bool Source::isFinished() const
{
{
if (!valid)
return false;
if (type == TYPE_STREAM && (isLooping() || !decoder->isFinished()))
return false;
@@ -342,7 +343,7 @@ bool Source::update()
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
return !isFinished();
case TYPE_STREAM:
if (isLooping() || !isFinished())
if (!isFinished())
{
ALint processed;
ALuint buffers[MAX_BUFFERS];
@@ -696,6 +697,9 @@ bool Source::isRelative() const
void Source::setLooping(bool enable)
{
if (type == TYPE_QUEUE)
throw QueueLoopingException();
if (valid && type == TYPE_STATIC)
alSourcei(source, AL_LOOPING, enable ? AL_TRUE : AL_FALSE);
@@ -707,25 +711,24 @@ bool Source::isLooping() const
return looping;
}
bool Source::queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels)
bool Source::queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels)
{
if (type != TYPE_QUEUE)
throw QueueTypeMismatchException();
if (length < 0)
throw QueueNegativeLengthException();
if (dataSampleRate != sampleRate || dataBitDepth != bitDepth || dataChannels != channels )
throw QueueFormatMismatchException();
if (length % (bitDepth / 8 * channels) != 0)
throw QueueMalformedLengthException(bitDepth / 8 * channels);
if (length > 0)
return pool->queueData(this, data, (ALsizei)length);
if (length == 0)
return true;
return pool->queue(this, data, (ALsizei)length);
}
bool Source::queueDataAtomic(void *data, ALsizei length)
bool Source::queueAtomic(void *data, ALsizei length)
{
if (valid)
{
@@ -752,11 +755,17 @@ bool Source::queueDataAtomic(void *data, ALsizei length)
return true;
}
bool Source::isQueueable() const
int Source::getFreeBufferCount() const
{
if (type != TYPE_QUEUE || (valid && unusedBufferTop < 0) || (!valid && unusedBufferTop >= (int)MAX_BUFFERS - 1))
return false;
return true;
switch (type) //why not :^)
{
case TYPE_STATIC:
return 0;
case TYPE_STREAM:
return unusedBufferTop + 1;
case TYPE_QUEUE:
return valid ? unusedBufferTop + 1 : (int)MAX_BUFFERS - unusedBufferTop - 1;
}
}
void Source::prepareAtomic()
@@ -799,7 +808,6 @@ void Source::prepareAtomic()
if (offsetSamples >= 0)
alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
}
}
}
@@ -839,7 +847,6 @@ void Source::teardownAtomic()
//stack needs to be filled in reverse order
for (unsigned int i = queued; i > 0; i--)
{
//since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array
alSourceUnqueueBuffers(source, 1, &buffer);
unusedBufferPush(buffer);
}
+3 -3
View File
@@ -131,9 +131,9 @@ public:
virtual float getMaxDistance() const;
virtual int getChannels() const;
virtual bool isQueueable() const;
virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels);
virtual bool queueDataAtomic(void *data, ALsizei length);
virtual int getFreeBufferCount() const;
virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels);
virtual bool queueAtomic(void *data, ALsizei length);
void prepareAtomic();
void teardownAtomic();
+42 -25
View File
@@ -44,41 +44,57 @@ int w_getSourceCount(lua_State *L)
int w_newSource(lua_State *L)
{
Source *t = 0;
if (lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3))
luax_catchexcept(L, [&]() {
t = instance()->newSource((int)lua_tonumber(L, 1), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3));
});
else
{
Source::Type stype = Source::TYPE_STREAM;
Source::Type stype = Source::TYPE_STREAM;
const char *stypestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2);
if (!luax_istype(L, 1, SOUND_SOUND_DATA_ID) && !luax_istype(L, 1, SOUND_DECODER_ID))
{
const char *stypestr = luaL_checkstring(L, 2);
if (stypestr && !Source::getConstant(stypestr, stype))
return luaL_error(L, "Invalid source type: %s", stypestr);
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID))
luax_convobj(L, 1, "sound", "newDecoder");
if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_ID))
luax_convobj(L, 1, "sound", "newSoundData");
luax_catchexcept(L, [&]() {
if (luax_istype(L, 1, SOUND_SOUND_DATA_ID))
t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, SOUND_SOUND_DATA_ID));
else if (luax_istype(L, 1, SOUND_DECODER_ID))
t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, SOUND_DECODER_ID));
});
}
if (t)
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID))
luax_convobj(L, 1, "sound", "newDecoder");
if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_ID))
luax_convobj(L, 1, "sound", "newSoundData");
Source *t = nullptr;
luax_catchexcept(L, [&]() {
if (luax_istype(L, 1, SOUND_SOUND_DATA_ID))
t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, SOUND_SOUND_DATA_ID));
else if (luax_istype(L, 1, SOUND_DECODER_ID))
t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, SOUND_DECODER_ID));
});
if (t != nullptr)
{
luax_pushtype(L, AUDIO_SOURCE_ID, t);
t->release();
return 1;
}
else
return luax_typerror(L, 1, "Decoder, SoundData or format description");
return luax_typerror(L, 1, "Decoder or SoundData");
}
int w_newQueueableSource(lua_State *L)
{
Source *t = nullptr;
if (lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3))
luax_catchexcept(L, [&]() {
t = instance()->newSource((int)lua_tonumber(L, 1), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3));
});
if (t != nullptr)
{
luax_pushtype(L, AUDIO_SOURCE_ID, t);
t->release();
return 1;
}
else
return luaL_error(L, "Wrong type of arguments to function call.");
}
static std::vector<Source*> readSourceList(lua_State *L, int n)
@@ -310,6 +326,7 @@ static const luaL_Reg functions[] =
{
{ "getSourceCount", w_getSourceCount },
{ "newSource", w_newSource },
{ "newQueueableSource", w_newQueueableSource },
{ "play", w_play },
{ "stop", w_stop },
{ "pause", w_pause },
+37 -21
View File
@@ -330,34 +330,50 @@ int w_Source_getChannels(lua_State *L)
return 1;
}
int w_Source_isQueueable(lua_State *L)
int w_Source_getFreeBufferCount(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isQueueable());
lua_pushinteger(L, t->getFreeBufferCount());
return 1;
}
int w_Source_queueData(lua_State *L)
int w_Source_queue(lua_State *L)
{
Source *t = luax_checksource(L, 1);
bool success;
luax_catchexcept(L, [&]() {
if (luax_istype(L, 2, SOUND_SOUND_DATA_ID))
{
love::sound::SoundData *s = luax_totype<love::sound::SoundData>(L, 2, SOUND_SOUND_DATA_ID);
success = t->queueData(s->getData(), lua_isnumber(L, 3) ? (int)lua_tonumber(L, 3) : s->getSize(), s->getSampleRate(), s->getBitDepth(), s->getChannels());
}
else if (lua_islightuserdata(L, 2))
{
if (lua_isnumber(L, 4) && lua_isnumber(L, 5) && lua_isnumber(L, 6))
success = t->queueData(lua_touserdata(L, 2), (int)lua_tonumber(L, 3), (int)lua_tonumber(L, 4), (int)lua_tonumber(L, 5), (int)lua_tonumber(L, 6));
else
return luaL_error(L, "No format specified.");
}
else
return luaL_error(L, "Invalid data type.");
});
if (luax_istype(L, 2, SOUND_SOUND_DATA_ID))
{
love::sound::SoundData *s = luax_totype<love::sound::SoundData>(L, 2, SOUND_SOUND_DATA_ID);
int length = lua_isnumber(L, 4) ? lua_tonumber(L, 4) : ( lua_isnumber(L, 3) ? lua_tonumber(L, 3) : s->getSize() );
int offset = lua_isnumber(L, 4) ? lua_tonumber(L, 3) : 0;
if (length > s->getSize() - offset || offset < 0 || length < 0)
return luaL_error(L, "Data region out of bounds.");
luax_catchexcept(L, [&]() {
success = t->queue((void*)((uintptr_t)s->getData() + (uintptr_t)offset),
length, s->getSampleRate(), s->getBitDepth(), s->getChannels());
});
}
else if (lua_islightuserdata(L, 2))
{
if (!(lua_isnumber(L, 3) && lua_isnumber(L, 4)))
return luaL_error(L, "No region specified.");
if (!(lua_isnumber(L, 5) && lua_isnumber(L, 6) && lua_isnumber(L, 7)))
return luaL_error(L, "No format specified.");
if (lua_tonumber(L, 3) < 0 || lua_tonumber(L, 4) < 0)
return luaL_error(L, "Data region out of bounds.");
luax_catchexcept(L, [&]() {
success = t->queue((void*)((uintptr_t)lua_touserdata(L, 2) + (uintptr_t)lua_tonumber(L, 3)),
lua_tonumber(L, 4), (int)lua_tonumber(L, 5), (int)lua_tonumber(L, 6), (int)lua_tonumber(L, 7));
});
}
else
return luax_typerror(L, 1, "Sound Data or lightuserdata");
luax_pushboolean(L, success);
return 1;
}
@@ -415,8 +431,8 @@ static const luaL_Reg w_Source_functions[] =
{ "getChannels", w_Source_getChannels },
{ "isQueueable", w_Source_isQueueable },
{ "queueData", w_Source_queueData },
{ "getFreeBufferCount", w_Source_getFreeBufferCount },
{ "queue", w_Source_queue },
{ "getType", w_Source_getType },