gosu 0.7.33 → 0.7.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gosu/Async.hpp +10 -8
- data/Gosu/Audio.hpp +6 -4
- data/Gosu/AutoLink.hpp +0 -0
- data/Gosu/Bitmap.hpp +4 -5
- data/Gosu/ButtonsX.hpp +1 -1
- data/Gosu/Color.hpp +8 -8
- data/Gosu/Font.hpp +2 -2
- data/Gosu/Graphics.hpp +4 -6
- data/Gosu/IO.hpp +11 -4
- data/Gosu/Image.hpp +9 -7
- data/Gosu/ImageData.hpp +10 -4
- data/Gosu/Input.hpp +4 -5
- data/Gosu/Sockets.hpp +10 -12
- data/Gosu/TR1.hpp +44 -0
- data/Gosu/TextInput.hpp +2 -2
- data/Gosu/Version.hpp +2 -2
- data/Gosu/WinUtility.hpp +5 -6
- data/Gosu/Window.hpp +5 -6
- data/GosuImpl/Async.cpp +4 -3
- data/GosuImpl/Audio/ALChannelManagement.hpp +23 -11
- data/GosuImpl/Audio/AudioFile.hpp +11 -3
- data/GosuImpl/Audio/AudioOpenAL.cpp +613 -0
- data/GosuImpl/Audio/AudioOpenAL.mm +1 -605
- data/GosuImpl/Audio/AudioSDL.cpp +12 -14
- data/GosuImpl/Audio/AudioToolboxFile.hpp +0 -1
- data/GosuImpl/Audio/OggFile.hpp +2 -0
- data/GosuImpl/Audio/SndFile.hpp +158 -0
- data/GosuImpl/DirectoriesWin.cpp +18 -18
- data/GosuImpl/Graphics/BitmapApple.mm +17 -19
- data/GosuImpl/Graphics/BitmapBMP.cpp +7 -2
- data/GosuImpl/Graphics/BitmapFreeImage.cpp +11 -12
- data/GosuImpl/Graphics/BitmapGDIplus.cpp +35 -31
- data/GosuImpl/Graphics/BitmapUtils.cpp +1 -1
- data/GosuImpl/Graphics/BlockAllocator.cpp +7 -8
- data/GosuImpl/Graphics/BlockAllocator.hpp +3 -4
- data/GosuImpl/Graphics/Common.hpp +3 -2
- data/GosuImpl/Graphics/DrawOp.hpp +2 -3
- data/GosuImpl/Graphics/DrawOpQueue.hpp +28 -20
- data/GosuImpl/Graphics/Font.cpp +13 -13
- data/GosuImpl/Graphics/FormattedString.hpp +93 -86
- data/GosuImpl/Graphics/Graphics.cpp +16 -14
- data/GosuImpl/Graphics/Image.cpp +7 -3
- data/GosuImpl/Graphics/LargeImageData.hpp +4 -5
- data/GosuImpl/Graphics/Macro.hpp +11 -11
- data/GosuImpl/Graphics/RenderState.hpp +5 -4
- data/GosuImpl/Graphics/TexChunk.cpp +3 -3
- data/GosuImpl/Graphics/TexChunk.hpp +4 -4
- data/GosuImpl/Graphics/Text.cpp +29 -30
- data/GosuImpl/Graphics/TextMac.cpp +9 -7
- data/GosuImpl/Graphics/TextTTFWin.cpp +3 -1
- data/GosuImpl/Graphics/TextTouch.mm +0 -1
- data/GosuImpl/Graphics/TextUnix.cpp +12 -4
- data/GosuImpl/Graphics/TextWin.cpp +4 -2
- data/GosuImpl/Graphics/Texture.cpp +7 -6
- data/GosuImpl/Graphics/Texture.hpp +3 -4
- data/GosuImpl/InputMac.mm +12 -15
- data/GosuImpl/InputTouch.mm +3 -3
- data/GosuImpl/InputWin.cpp +149 -159
- data/GosuImpl/InputX.cpp +0 -0
- data/GosuImpl/MacUtility.hpp +9 -4
- data/GosuImpl/RubyGosu.swg +38 -43
- data/GosuImpl/RubyGosu_wrap.cxx +89 -96
- data/GosuImpl/Sockets/CommSocket.cpp +5 -5
- data/GosuImpl/Sockets/Sockets.hpp +4 -4
- data/GosuImpl/TimingApple.cpp +2 -3
- data/GosuImpl/Utility.cpp +18 -0
- data/GosuImpl/WinMain.cpp +0 -1
- data/GosuImpl/WinUtility.cpp +2 -2
- data/GosuImpl/WindowMac.mm +20 -17
- data/GosuImpl/WindowTouch.mm +8 -7
- data/GosuImpl/WindowWin.cpp +12 -7
- data/GosuImpl/WindowX.cpp +67 -18
- data/lib/gosu.rb +14 -12
- data/linux/extconf.rb +11 -6
- metadata +8 -7
- data/GosuImpl/Audio/AudioAudiere.cpp +0 -448
- data/GosuImpl/RubyGosu_DllMain.cxx +0 -31
@@ -1,605 +1 @@
|
|
1
|
-
#include <GosuImpl/
|
2
|
-
#include <GosuImpl/Audio/AudioToolboxFile.hpp>
|
3
|
-
#include <GosuImpl/Audio/ALChannelManagement.hpp>
|
4
|
-
#include <GosuImpl/Audio/OggFile.hpp>
|
5
|
-
|
6
|
-
#include <Gosu/Audio.hpp>
|
7
|
-
#include <Gosu/Math.hpp>
|
8
|
-
#include <Gosu/IO.hpp>
|
9
|
-
#include <Gosu/Utility.hpp>
|
10
|
-
#include <Gosu/Platform.hpp>
|
11
|
-
|
12
|
-
#include <boost/algorithm/string.hpp>
|
13
|
-
#include <boost/lexical_cast.hpp>
|
14
|
-
#include <boost/optional.hpp>
|
15
|
-
#include <boost/scoped_ptr.hpp>
|
16
|
-
|
17
|
-
#include <cassert>
|
18
|
-
#include <cstdlib>
|
19
|
-
#include <algorithm>
|
20
|
-
#include <stdexcept>
|
21
|
-
#include <vector>
|
22
|
-
|
23
|
-
#include <OpenAL/al.h>
|
24
|
-
#include <OpenAL/alc.h>
|
25
|
-
|
26
|
-
#ifdef GOSU_IS_IPHONE
|
27
|
-
#import <AVFoundation/AVFoundation.h>
|
28
|
-
#endif
|
29
|
-
|
30
|
-
using namespace std;
|
31
|
-
|
32
|
-
namespace
|
33
|
-
{
|
34
|
-
using namespace Gosu;
|
35
|
-
|
36
|
-
GOSU_NORETURN void throwLastALError(const char* action)
|
37
|
-
{
|
38
|
-
string message = "OpenAL error " +
|
39
|
-
boost::lexical_cast<string>(alcGetError(ALChannelManagement::device()));
|
40
|
-
if (action)
|
41
|
-
message += " while ", message += action;
|
42
|
-
throw runtime_error(message);
|
43
|
-
}
|
44
|
-
|
45
|
-
inline void alCheck(const char* action = 0)
|
46
|
-
{
|
47
|
-
if (alcGetError(ALChannelManagement::device()) != ALC_NO_ERROR)
|
48
|
-
throwLastALError(action);
|
49
|
-
}
|
50
|
-
|
51
|
-
bool isOggFile(Gosu::Reader reader)
|
52
|
-
{
|
53
|
-
char magicBytes[4];
|
54
|
-
reader.read(magicBytes, 4);
|
55
|
-
return magicBytes[0] == 'O' && magicBytes[1] == 'g' &&
|
56
|
-
magicBytes[2] == 'g' && magicBytes[3] == 'S';
|
57
|
-
}
|
58
|
-
|
59
|
-
bool isOggFile(const std::wstring& filename)
|
60
|
-
{
|
61
|
-
Gosu::File file(filename);
|
62
|
-
return isOggFile(file.frontReader());
|
63
|
-
}
|
64
|
-
|
65
|
-
Song* curSong = 0;
|
66
|
-
bool curSongLooping;
|
67
|
-
}
|
68
|
-
|
69
|
-
#define CONSTRUCTOR_COMMON \
|
70
|
-
ObjRef<NSAutoreleasePool> pool([[NSAutoreleasePool alloc] init]); \
|
71
|
-
if (!alChannelManagement) \
|
72
|
-
alChannelManagement.reset(new ALChannelManagement)
|
73
|
-
|
74
|
-
Gosu::SampleInstance::SampleInstance(int handle, int extra)
|
75
|
-
: handle(handle), extra(extra)
|
76
|
-
{
|
77
|
-
}
|
78
|
-
|
79
|
-
bool Gosu::SampleInstance::playing() const
|
80
|
-
{
|
81
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
82
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
83
|
-
return false;
|
84
|
-
ALint state;
|
85
|
-
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
86
|
-
return state == AL_PLAYING;
|
87
|
-
}
|
88
|
-
|
89
|
-
bool Gosu::SampleInstance::paused() const
|
90
|
-
{
|
91
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
92
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
93
|
-
return false;
|
94
|
-
ALint state;
|
95
|
-
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
96
|
-
return state == AL_PAUSED;
|
97
|
-
}
|
98
|
-
|
99
|
-
void Gosu::SampleInstance::pause()
|
100
|
-
{
|
101
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
102
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
103
|
-
return;
|
104
|
-
alSourcePause(source);
|
105
|
-
}
|
106
|
-
|
107
|
-
void Gosu::SampleInstance::resume()
|
108
|
-
{
|
109
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
110
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
111
|
-
return;
|
112
|
-
ALint state;
|
113
|
-
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
114
|
-
if (state == AL_PAUSED)
|
115
|
-
alSourcePlay(source);
|
116
|
-
}
|
117
|
-
|
118
|
-
void Gosu::SampleInstance::stop()
|
119
|
-
{
|
120
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
121
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
122
|
-
return;
|
123
|
-
alSourceStop(source);
|
124
|
-
}
|
125
|
-
|
126
|
-
void Gosu::SampleInstance::changeVolume(double volume)
|
127
|
-
{
|
128
|
-
ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
129
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
130
|
-
return;
|
131
|
-
alSourcef(source, AL_GAIN, volume);
|
132
|
-
}
|
133
|
-
|
134
|
-
void Gosu::SampleInstance::changePan(double pan)
|
135
|
-
{
|
136
|
-
NSUInteger source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
137
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
138
|
-
return;
|
139
|
-
// TODO: This is not the old panning behavior!
|
140
|
-
alSource3f(source, AL_POSITION, pan * 10, 0, 0);
|
141
|
-
}
|
142
|
-
|
143
|
-
void Gosu::SampleInstance::changeSpeed(double speed)
|
144
|
-
{
|
145
|
-
NSUInteger source = alChannelManagement->sourceIfStillPlaying(handle, extra);
|
146
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
147
|
-
return;
|
148
|
-
alSourcef(source, AL_PITCH, speed);
|
149
|
-
}
|
150
|
-
|
151
|
-
struct Gosu::Sample::SampleData : boost::noncopyable
|
152
|
-
{
|
153
|
-
ALuint buffer, source;
|
154
|
-
|
155
|
-
SampleData(AudioFile& audioFile)
|
156
|
-
{
|
157
|
-
alGenBuffers(1, &buffer);
|
158
|
-
alBufferData(buffer,
|
159
|
-
audioFile.format(),
|
160
|
-
&audioFile.decodedData().front(),
|
161
|
-
audioFile.decodedData().size(),
|
162
|
-
audioFile.sampleRate());
|
163
|
-
}
|
164
|
-
|
165
|
-
~SampleData()
|
166
|
-
{
|
167
|
-
// It's hard to free things in the right order in Ruby/Gosu.
|
168
|
-
// Make sure buffer isn't deleted after the context/device are shut down.
|
169
|
-
|
170
|
-
if (!alChannelManagement)
|
171
|
-
return;
|
172
|
-
|
173
|
-
alDeleteBuffers(1, &buffer);
|
174
|
-
}
|
175
|
-
};
|
176
|
-
|
177
|
-
Gosu::Sample::Sample(const std::wstring& filename)
|
178
|
-
{
|
179
|
-
CONSTRUCTOR_COMMON;
|
180
|
-
|
181
|
-
if (isOggFile(filename))
|
182
|
-
{
|
183
|
-
Gosu::Buffer buffer;
|
184
|
-
Gosu::loadFile(buffer, filename);
|
185
|
-
OggFile oggFile(buffer.frontReader());
|
186
|
-
data.reset(new SampleData(oggFile));
|
187
|
-
}
|
188
|
-
else
|
189
|
-
{
|
190
|
-
AudioToolboxFile audioFile(filename);
|
191
|
-
data.reset(new SampleData(audioFile));
|
192
|
-
}
|
193
|
-
}
|
194
|
-
|
195
|
-
Gosu::Sample::Sample(Reader reader)
|
196
|
-
{
|
197
|
-
CONSTRUCTOR_COMMON;
|
198
|
-
|
199
|
-
if (isOggFile(reader))
|
200
|
-
{
|
201
|
-
OggFile oggFile(reader);
|
202
|
-
data.reset(new SampleData(oggFile));
|
203
|
-
}
|
204
|
-
else
|
205
|
-
{
|
206
|
-
AudioToolboxFile audioFile(reader);
|
207
|
-
data.reset(new SampleData(audioFile));
|
208
|
-
}
|
209
|
-
}
|
210
|
-
|
211
|
-
Gosu::SampleInstance Gosu::Sample::play(double volume, double speed,
|
212
|
-
bool looping) const
|
213
|
-
{
|
214
|
-
return playPan(0, volume, speed, looping);
|
215
|
-
}
|
216
|
-
|
217
|
-
Gosu::SampleInstance Gosu::Sample::playPan(double pan, double volume,
|
218
|
-
double speed, bool looping) const
|
219
|
-
{
|
220
|
-
std::pair<int, int> channelAndToken = alChannelManagement->reserveChannel();
|
221
|
-
if (channelAndToken.first == ALChannelManagement::NO_FREE_CHANNEL)
|
222
|
-
return Gosu::SampleInstance(channelAndToken.first, channelAndToken.second);
|
223
|
-
|
224
|
-
NSUInteger source = alChannelManagement->sourceIfStillPlaying(channelAndToken.first,
|
225
|
-
channelAndToken.second);
|
226
|
-
assert(source != ALChannelManagement::NO_SOURCE);
|
227
|
-
alSourcei(source, AL_BUFFER, data->buffer);
|
228
|
-
// TODO: This is not the old panning behavior!
|
229
|
-
alSource3f(source, AL_POSITION, pan * 10, 0, 0);
|
230
|
-
alSourcef(source, AL_GAIN, volume);
|
231
|
-
alSourcef(source, AL_PITCH, speed);
|
232
|
-
alSourcei(source, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
|
233
|
-
alSourcePlay(source);
|
234
|
-
|
235
|
-
return Gosu::SampleInstance(channelAndToken.first, channelAndToken.second);
|
236
|
-
}
|
237
|
-
|
238
|
-
class Gosu::Song::BaseData : boost::noncopyable
|
239
|
-
{
|
240
|
-
double volume_;
|
241
|
-
|
242
|
-
protected:
|
243
|
-
BaseData() : volume_(1) {}
|
244
|
-
virtual void applyVolume() = 0;
|
245
|
-
|
246
|
-
public:
|
247
|
-
virtual ~BaseData() {}
|
248
|
-
|
249
|
-
virtual void play(bool looping) = 0;
|
250
|
-
virtual void pause() = 0;
|
251
|
-
virtual void resume() = 0;
|
252
|
-
virtual bool paused() const = 0;
|
253
|
-
virtual void stop() = 0;
|
254
|
-
|
255
|
-
virtual void update() = 0;
|
256
|
-
|
257
|
-
double volume() const
|
258
|
-
{
|
259
|
-
return volume_;
|
260
|
-
}
|
261
|
-
|
262
|
-
void changeVolume(double volume)
|
263
|
-
{
|
264
|
-
volume_ = clamp(volume, 0.0, 1.0);
|
265
|
-
applyVolume();
|
266
|
-
}
|
267
|
-
};
|
268
|
-
|
269
|
-
#ifdef GOSU_IS_IPHONE
|
270
|
-
// AVAudioPlayer impl
|
271
|
-
class Gosu::Song::ModuleData : public BaseData
|
272
|
-
{
|
273
|
-
ObjRef<AVAudioPlayer> player;
|
274
|
-
|
275
|
-
void applyVolume()
|
276
|
-
{
|
277
|
-
player.obj().volume = volume();
|
278
|
-
}
|
279
|
-
|
280
|
-
public:
|
281
|
-
ModuleData(const std::wstring& filename)
|
282
|
-
{
|
283
|
-
std::string utf8Filename = Gosu::wstringToUTF8(filename);
|
284
|
-
ObjRef<NSString> nsFilename([[NSString alloc] initWithUTF8String: utf8Filename.c_str()]);
|
285
|
-
ObjRef<NSURL> url([[NSURL alloc] initFileURLWithPath: nsFilename.obj()]);
|
286
|
-
player.reset([[AVAudioPlayer alloc] initWithContentsOfURL: url.obj() error: NULL]);
|
287
|
-
}
|
288
|
-
|
289
|
-
void play(bool looping)
|
290
|
-
{
|
291
|
-
if (paused())
|
292
|
-
stop();
|
293
|
-
player.obj().numberOfLoops = looping ? -1 : 0;
|
294
|
-
[player.obj() play];
|
295
|
-
}
|
296
|
-
|
297
|
-
void pause()
|
298
|
-
{
|
299
|
-
[player.obj() pause];
|
300
|
-
}
|
301
|
-
|
302
|
-
void resume()
|
303
|
-
{
|
304
|
-
[player.obj() play];
|
305
|
-
}
|
306
|
-
|
307
|
-
bool paused() const
|
308
|
-
{
|
309
|
-
return !player.obj().playing;
|
310
|
-
};
|
311
|
-
|
312
|
-
void stop()
|
313
|
-
{
|
314
|
-
[player.obj() stop];
|
315
|
-
player.obj().currentTime = 0;
|
316
|
-
}
|
317
|
-
|
318
|
-
void update()
|
319
|
-
{
|
320
|
-
}
|
321
|
-
};
|
322
|
-
#endif
|
323
|
-
|
324
|
-
// AudioToolbox impl
|
325
|
-
class Gosu::Song::StreamData : public BaseData
|
326
|
-
{
|
327
|
-
boost::scoped_ptr<AudioFile> file;
|
328
|
-
ALuint buffers[2];
|
329
|
-
|
330
|
-
void applyVolume()
|
331
|
-
{
|
332
|
-
int source = lookupSource();
|
333
|
-
if (source != ALChannelManagement::NO_SOURCE)
|
334
|
-
alSourcef(source, AL_GAIN, volume());
|
335
|
-
}
|
336
|
-
|
337
|
-
int lookupSource() const
|
338
|
-
{
|
339
|
-
return alChannelManagement->sourceForSongs();
|
340
|
-
}
|
341
|
-
|
342
|
-
bool streamToBuffer(ALuint buffer)
|
343
|
-
{
|
344
|
-
#ifdef GOSU_IS_IPHONE
|
345
|
-
static const unsigned BUFFER_SIZE = 4096 * 4;
|
346
|
-
#else
|
347
|
-
static const unsigned BUFFER_SIZE = 4096 * 8;
|
348
|
-
#endif
|
349
|
-
char audioData[BUFFER_SIZE];
|
350
|
-
std::size_t readBytes = file->readData(audioData, BUFFER_SIZE);
|
351
|
-
if (readBytes > 0)
|
352
|
-
alBufferData(buffer, file->format(), audioData, readBytes, file->sampleRate());
|
353
|
-
return readBytes > 0;
|
354
|
-
}
|
355
|
-
|
356
|
-
public:
|
357
|
-
StreamData(const std::wstring& filename)
|
358
|
-
{
|
359
|
-
if (isOggFile(filename))
|
360
|
-
{
|
361
|
-
Gosu::File sourceFile(filename);
|
362
|
-
file.reset(new OggFile(sourceFile.frontReader()));
|
363
|
-
}
|
364
|
-
else
|
365
|
-
file.reset(new AudioToolboxFile(filename));
|
366
|
-
alGenBuffers(2, buffers);
|
367
|
-
}
|
368
|
-
|
369
|
-
StreamData(Reader reader)
|
370
|
-
{
|
371
|
-
if (isOggFile(reader))
|
372
|
-
file.reset(new OggFile(reader));
|
373
|
-
else
|
374
|
-
file.reset(new AudioToolboxFile(reader));
|
375
|
-
alGenBuffers(2, buffers);
|
376
|
-
}
|
377
|
-
|
378
|
-
~StreamData()
|
379
|
-
{
|
380
|
-
if (alChannelManagement)
|
381
|
-
{
|
382
|
-
stop();
|
383
|
-
alDeleteBuffers(2, buffers);
|
384
|
-
}
|
385
|
-
}
|
386
|
-
|
387
|
-
void play(bool looping)
|
388
|
-
{
|
389
|
-
int source = lookupSource();
|
390
|
-
if (source != ALChannelManagement::NO_SOURCE)
|
391
|
-
{
|
392
|
-
alSource3f(source, AL_POSITION, 0, 0, 0);
|
393
|
-
alSourcef(source, AL_GAIN, volume());
|
394
|
-
alSourcef(source, AL_PITCH, 1);
|
395
|
-
alSourcei(source, AL_LOOPING, AL_FALSE); // need to implement this manually...
|
396
|
-
|
397
|
-
streamToBuffer(buffers[0]);
|
398
|
-
streamToBuffer(buffers[1]);
|
399
|
-
|
400
|
-
// TODO: Not good for songs with less than two buffers full of data.
|
401
|
-
|
402
|
-
alSourceQueueBuffers(source, 2, buffers);
|
403
|
-
alSourcePlay(source);
|
404
|
-
}
|
405
|
-
}
|
406
|
-
|
407
|
-
void stop()
|
408
|
-
{
|
409
|
-
int source = lookupSource();
|
410
|
-
if (source != ALChannelManagement::NO_SOURCE)
|
411
|
-
{
|
412
|
-
alSourceStop(source);
|
413
|
-
|
414
|
-
ALuint buffer;
|
415
|
-
|
416
|
-
// The number of QUEUED buffers apparently includes the number of
|
417
|
-
// PROCESSED ones, so getting rid of the QUEUED ones is enough.
|
418
|
-
|
419
|
-
int queued;
|
420
|
-
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
421
|
-
while (queued--)
|
422
|
-
alSourceUnqueueBuffers(source, 1, &buffer);
|
423
|
-
|
424
|
-
//int processed;
|
425
|
-
//alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
426
|
-
//while (processed--)
|
427
|
-
// alSourceUnqueueBuffers(source, 1, &buffer);
|
428
|
-
}
|
429
|
-
file->rewind();
|
430
|
-
}
|
431
|
-
|
432
|
-
void pause()
|
433
|
-
{
|
434
|
-
int source = lookupSource();
|
435
|
-
if (source != ALChannelManagement::NO_SOURCE)
|
436
|
-
alSourcePause(source);
|
437
|
-
}
|
438
|
-
|
439
|
-
void resume()
|
440
|
-
{
|
441
|
-
int source = lookupSource();
|
442
|
-
if (source != ALChannelManagement::NO_SOURCE)
|
443
|
-
alSourcePlay(source);
|
444
|
-
}
|
445
|
-
|
446
|
-
bool paused() const
|
447
|
-
{
|
448
|
-
int source = lookupSource();
|
449
|
-
if (source == ALChannelManagement::NO_SOURCE)
|
450
|
-
return false;
|
451
|
-
ALint state;
|
452
|
-
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
453
|
-
return state == AL_PAUSED;
|
454
|
-
}
|
455
|
-
|
456
|
-
void update()
|
457
|
-
{
|
458
|
-
int source = lookupSource();
|
459
|
-
|
460
|
-
ALuint buffer;
|
461
|
-
int processed;
|
462
|
-
bool active = true;
|
463
|
-
|
464
|
-
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
465
|
-
for (int i = 0; i < processed; ++i)
|
466
|
-
{
|
467
|
-
alSourceUnqueueBuffers(source, 1, &buffer);
|
468
|
-
active = streamToBuffer(buffer);
|
469
|
-
if (active)
|
470
|
-
alSourceQueueBuffers(source, 1, &buffer);
|
471
|
-
}
|
472
|
-
|
473
|
-
ALint state;
|
474
|
-
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
475
|
-
if (active && state != AL_PLAYING && state != AL_PAUSED)
|
476
|
-
{
|
477
|
-
// We seemingly got starved.
|
478
|
-
alSourcePlay(source);
|
479
|
-
}
|
480
|
-
else if (!active)
|
481
|
-
{
|
482
|
-
// We got starved and there is nothing to play left.
|
483
|
-
// In any case, shut down the playback logic for a moment.
|
484
|
-
stop();
|
485
|
-
|
486
|
-
if (curSongLooping)
|
487
|
-
// Start anew.
|
488
|
-
play(true);
|
489
|
-
else
|
490
|
-
// Let the world know we're finished.
|
491
|
-
curSong = 0;
|
492
|
-
}
|
493
|
-
}
|
494
|
-
};
|
495
|
-
|
496
|
-
Gosu::Song::Song(const std::wstring& filename)
|
497
|
-
{
|
498
|
-
#ifdef GOSU_IS_IPHONE
|
499
|
-
if (boost::iends_with(filename, L".mp3") || boost::iends_with(filename, L".aac") || boost::iends_with(filename, L".m4a"))
|
500
|
-
data.reset(new ModuleData(filename));
|
501
|
-
else
|
502
|
-
#endif
|
503
|
-
{
|
504
|
-
CONSTRUCTOR_COMMON;
|
505
|
-
data.reset(new StreamData(filename));
|
506
|
-
}
|
507
|
-
}
|
508
|
-
|
509
|
-
Gosu::Song::Song(Reader reader)
|
510
|
-
{
|
511
|
-
CONSTRUCTOR_COMMON;
|
512
|
-
|
513
|
-
data.reset(new StreamData(reader));
|
514
|
-
}
|
515
|
-
|
516
|
-
Gosu::Song::~Song()
|
517
|
-
{
|
518
|
-
stop();
|
519
|
-
}
|
520
|
-
|
521
|
-
Gosu::Song* Gosu::Song::currentSong()
|
522
|
-
{
|
523
|
-
return curSong;
|
524
|
-
}
|
525
|
-
|
526
|
-
void Gosu::Song::play(bool looping)
|
527
|
-
{
|
528
|
-
if (paused())
|
529
|
-
data->resume();
|
530
|
-
|
531
|
-
if (curSong && curSong != this)
|
532
|
-
{
|
533
|
-
curSong->stop();
|
534
|
-
assert(curSong == 0);
|
535
|
-
}
|
536
|
-
|
537
|
-
if (curSong == 0)
|
538
|
-
data->play(looping);
|
539
|
-
|
540
|
-
curSong = this;
|
541
|
-
curSongLooping = looping;
|
542
|
-
}
|
543
|
-
|
544
|
-
void Gosu::Song::pause()
|
545
|
-
{
|
546
|
-
if (curSong == this)
|
547
|
-
data->pause(); // may be redundant
|
548
|
-
}
|
549
|
-
|
550
|
-
bool Gosu::Song::paused() const
|
551
|
-
{
|
552
|
-
return curSong == this && data->paused();
|
553
|
-
}
|
554
|
-
|
555
|
-
void Gosu::Song::stop()
|
556
|
-
{
|
557
|
-
if (curSong == this)
|
558
|
-
{
|
559
|
-
data->stop();
|
560
|
-
curSong = 0;
|
561
|
-
}
|
562
|
-
}
|
563
|
-
|
564
|
-
bool Gosu::Song::playing() const
|
565
|
-
{
|
566
|
-
return curSong == this && !data->paused();
|
567
|
-
}
|
568
|
-
|
569
|
-
double Gosu::Song::volume() const
|
570
|
-
{
|
571
|
-
return data->volume();
|
572
|
-
}
|
573
|
-
|
574
|
-
void Gosu::Song::changeVolume(double volume)
|
575
|
-
{
|
576
|
-
data->changeVolume(volume);
|
577
|
-
}
|
578
|
-
|
579
|
-
void Gosu::Song::update()
|
580
|
-
{
|
581
|
-
if (currentSong())
|
582
|
-
currentSong()->data->update();
|
583
|
-
}
|
584
|
-
|
585
|
-
// Deprecated constructors.
|
586
|
-
|
587
|
-
Gosu::Sample::Sample(Audio& audio, const std::wstring& filename)
|
588
|
-
{
|
589
|
-
Sample(filename).data.swap(data);
|
590
|
-
}
|
591
|
-
|
592
|
-
Gosu::Sample::Sample(Audio& audio, Reader reader)
|
593
|
-
{
|
594
|
-
Sample(reader).data.swap(data);
|
595
|
-
}
|
596
|
-
|
597
|
-
Gosu::Song::Song(Audio& audio, const std::wstring& filename)
|
598
|
-
{
|
599
|
-
Song(filename).data.swap(data);
|
600
|
-
}
|
601
|
-
|
602
|
-
Gosu::Song::Song(Audio& audio, Type type, Reader reader)
|
603
|
-
{
|
604
|
-
Song(reader).data.swap(data);
|
605
|
-
}
|
1
|
+
#include <GosuImpl/Audio/AudioOpenAL.cpp>
|