2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 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
41 const Decoder::ListType& Decoder::GetList()
44 Decoder::ListType& Decoder::AddList(Decoder::FactoryType func, ALint prio)
46 static ListType FuncList;
49 assert(SearchSecond(FuncList.begin(), FuncList.end(), func) == FuncList.end());
50 FuncList.insert(std::make_pair(prio, func));
56 struct customStream : public alureStream {
65 virtual bool IsValid()
66 { return usrFile != NULL; }
68 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
72 if(!cb.get_fmt || !cb.get_fmt(usrFile, &format, &samplerate, &blockAlign))
75 ALuint detected = DetectBlockAlignment(format);
76 if(detected && (blockAlign%detected) != 0)
81 *frequency = samplerate;
82 *blockalign = blockAlign;
86 virtual ALuint GetData(ALubyte *data, ALuint bytes)
87 { return cb.decode(usrFile, data, bytes); }
91 if(cb.rewind && cb.rewind(usrFile))
93 SetError("Rewind failed");
97 customStream(const char *fname, const UserCallbacks &callbacks)
98 : alureStream(NULL), usrFile(NULL), format(AL_NONE), samplerate(0),
99 blockAlign(0), cb(callbacks)
100 { if(cb.open_file) usrFile = cb.open_file(fname); }
102 customStream(const MemDataInfo &memData, const UserCallbacks &callbacks)
103 : alureStream(NULL), usrFile(NULL), format(AL_NONE), samplerate(0),
104 blockAlign(0), memInfo(memData), cb(callbacks)
105 { if(cb.open_mem) usrFile = cb.open_mem(memInfo.Data, memInfo.Length); }
107 customStream(void *userdata, ALenum fmt, ALuint srate, const UserCallbacks &callbacks)
108 : alureStream(NULL), usrFile(userdata), format(fmt), samplerate(srate),
109 blockAlign(DetectBlockAlignment(format)), cb(callbacks)
112 virtual ~customStream()
114 if(cb.close && usrFile)
121 template <typename T>
122 static alureStream *get_stream_decoder(const T &fdata)
124 std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.begin();
125 while(i != InstalledCallbacks.end() && i->first < 0)
127 std::auto_ptr<alureStream> stream(new customStream(fdata, i->second));
128 if(stream->IsValid()) return stream.release();
132 std::istream *file = new InStream(fdata);
135 const Decoder::ListType Factories = Decoder::GetList();
136 Decoder::ListType::const_reverse_iterator factory = Factories.rbegin();
137 Decoder::ListType::const_reverse_iterator end = Factories.rend();
138 while(factory != end)
141 file->seekg(0, std::ios_base::beg);
143 std::auto_ptr<alureStream> stream(factory->second(file));
144 if(stream.get() != NULL) return stream.release();
149 SetError("Unsupported type");
154 SetError("Failed to open file");
158 while(i != InstalledCallbacks.end())
160 std::auto_ptr<alureStream> stream(new customStream(fdata, i->second));
161 if(stream->IsValid()) return stream.release();
168 alureStream *create_stream(const char *fname)
169 { return get_stream_decoder(fname); }
170 alureStream *create_stream(const MemDataInfo &memData)
171 { return get_stream_decoder(memData); }
173 alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb)
174 { return new customStream(userdata, format, rate, cb); }