Make file and memory based create_stream calls return NULL for invalid streams
[alure.git] / src / buffer.cpp
blob9586964fb0bed906c0ef275be9544aedf5d592b3
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (c) 2009 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /* Title: File Loading */
26 #include "config.h"
28 #include "main.h"
30 #include <string.h>
32 #include <vector>
33 #include <memory>
36 bool load_stream(alureStream *_stream, ALuint buffer)
38 if(!_stream)
39 return false;
41 std::auto_ptr<std::istream> fstream(_stream->fstream);
42 std::auto_ptr<alureStream> stream(_stream);
44 ALenum format;
45 ALuint freq, blockAlign;
47 if(!stream->GetFormat(&format, &freq, &blockAlign))
49 SetError("Could not get sample format");
50 return false;
53 if(format == AL_NONE)
55 SetError("No valid format");
56 return false;
58 if(blockAlign == 0)
60 SetError("Invalid block size");
61 return false;
63 if(freq == 0)
65 SetError("Invalid sample rate");
66 return false;
69 ALuint writePos = 0, got;
70 std::vector<ALubyte> data(freq*blockAlign);
71 while((got=stream->GetData(&data[writePos], data.size()-writePos)) > 0)
73 writePos += got;
74 data.resize(writePos + freq*blockAlign);
76 data.resize(writePos - (writePos%blockAlign));
77 stream.reset(NULL);
79 alBufferData(buffer, format, &data[0], data.size(), freq);
80 if(alGetError() != AL_NO_ERROR)
82 SetError("Buffer load failed");
83 return false;
86 return true;
89 extern "C" {
91 /* Function: alureCreateBufferFromFile
93 * Loads the given file into a new OpenAL buffer object. The formats supported
94 * depend on the options the library was compiled with, what libraries are
95 * available at runtime, and the installed decode callbacks. Requires an active
96 * context.
98 * Returns:
99 * A new buffer ID with the loaded sound, or AL_NONE on error.
101 * See Also:
102 * <alureBufferDataFromFile>
104 ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(const ALchar *fname)
106 if(alGetError() != AL_NO_ERROR)
108 SetError("Existing OpenAL error");
109 return AL_NONE;
112 ALuint buf;
113 alGenBuffers(1, &buf);
114 if(alGetError() != AL_NO_ERROR)
116 SetError("Buffer creation failed");
117 return AL_NONE;
120 if(alureBufferDataFromFile(fname, buf) == AL_FALSE)
122 alDeleteBuffers(1, &buf);
123 alGetError();
124 buf = AL_NONE;
127 return buf;
130 /* Function: alureCreateBufferFromMemory
132 * Loads a file image from memory into a new OpenAL buffer object, similar to
133 * alureCreateBufferFromFile. Requires an active context.
135 * Returns:
136 * A new buffer ID with the loaded sound, or AL_NONE on error.
138 * See Also:
139 * <alureBufferDataFromMemory>
141 ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(const ALubyte *fdata, ALsizei length)
143 if(alGetError() != AL_NO_ERROR)
145 SetError("Existing OpenAL error");
146 return AL_NONE;
149 ALuint buf;
150 alGenBuffers(1, &buf);
151 if(alGetError() != AL_NO_ERROR)
153 SetError("Buffer creation failed");
154 return AL_NONE;
157 if(alureBufferDataFromMemory(fdata, length, buf) == AL_FALSE)
159 alDeleteBuffers(1, &buf);
160 alGetError();
161 buf = AL_NONE;
164 return buf;
167 /* Function: alureBufferDataFromFile
169 * Loads the given file into an existing OpenAL buffer object. The previous
170 * contents of the buffer are replaced. Requires an active context.
172 * Returns:
173 * AL_FALSE on error.
175 * See Also:
176 * <alureCreateBufferFromFile>
178 ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(const ALchar *fname, ALuint buffer)
180 if(alGetError() != AL_NO_ERROR)
182 SetError("Existing OpenAL error");
183 return AL_FALSE;
186 if(load_stream(create_stream(fname), buffer) == false)
187 return AL_FALSE;
188 return AL_TRUE;
191 /* Function: alureBufferDataFromMemory
193 * Loads a file image from memory into an existing OpenAL buffer object,
194 * similar to alureBufferDataFromFile. Requires an active context.
196 * Returns:
197 * AL_FALSE on error.
199 * See Also:
200 * <alureCreateBufferFromMemory>
202 ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(const ALubyte *fdata, ALsizei length, ALuint buffer)
204 if(alGetError() != AL_NO_ERROR)
206 SetError("Existing OpenAL error");
207 return AL_FALSE;
210 if(length < 0)
212 SetError("Invalid data length");
213 return AL_FALSE;
216 MemDataInfo memData;
217 memData.Data = fdata;
218 memData.Length = length;
219 memData.Pos = 0;
221 if(load_stream(create_stream(memData), buffer) == false)
222 return AL_FALSE;
223 return AL_TRUE;
226 } // extern "C"