Browse Source

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
rcoaxil 8 years ago
parent
commit
b757a0534e

+ 2 - 2
src/modules/audio/Source.h

@@ -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
src/modules/audio/null/Source.cpp

@@ -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
src/modules/audio/null/Source.h

@@ -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
src/modules/audio/openal/Pool.cpp

@@ -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
src/modules/audio/openal/Pool.h

@@ -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);

+ 30 - 23
src/modules/audio/openal/Source.cpp

@@ -80,34 +80,35 @@ class QueueTypeMismatchException : public love::Exception
 public:
 
 	QueueTypeMismatchException()
-		: Exception("Only \"queue\" type sound Sources can be queued with sound data.")
+		: Exception("Only queueable Sources can be queued with sound data.")
 	{
 	}
 
 };
 
-class QueueNegativeLengthException : public love::Exception
+class QueueMalformedLengthException : public love::Exception
 {
 public:
 
-	QueueNegativeLengthException()
-		: Exception("Data length cannot be negative.")
+	QueueMalformedLengthException(int bytes)
+		: Exception("Data length must be a multiple of sample size (%d bytes).", bytes)
 	{
 	}
 
 };
 
-class QueueMalformedLengthException : public love::Exception
+class QueueLoopingException : public love::Exception
 {
 public:
 
-	QueueMalformedLengthException(int bytes)
-		: Exception("Data lenght must be a multiple of sample size (%d bytes).", bytes)
+	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
src/modules/audio/openal/Source.h

@@ -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();

+ 39 - 22
src/modules/audio/wrap_Audio.cpp

@@ -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 (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");
 
-		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 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, [&]() {
-			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));
+			t = instance()->newSource((int)lua_tonumber(L, 1), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3));
 		});
-	}
-	if (t)
+		
+	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 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
src/modules/audio/wrap_Source.cpp

@@ -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 },