gosu 0.7.33 → 0.7.35

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/Gosu/Async.hpp +10 -8
  2. data/Gosu/Audio.hpp +6 -4
  3. data/Gosu/AutoLink.hpp +0 -0
  4. data/Gosu/Bitmap.hpp +4 -5
  5. data/Gosu/ButtonsX.hpp +1 -1
  6. data/Gosu/Color.hpp +8 -8
  7. data/Gosu/Font.hpp +2 -2
  8. data/Gosu/Graphics.hpp +4 -6
  9. data/Gosu/IO.hpp +11 -4
  10. data/Gosu/Image.hpp +9 -7
  11. data/Gosu/ImageData.hpp +10 -4
  12. data/Gosu/Input.hpp +4 -5
  13. data/Gosu/Sockets.hpp +10 -12
  14. data/Gosu/TR1.hpp +44 -0
  15. data/Gosu/TextInput.hpp +2 -2
  16. data/Gosu/Version.hpp +2 -2
  17. data/Gosu/WinUtility.hpp +5 -6
  18. data/Gosu/Window.hpp +5 -6
  19. data/GosuImpl/Async.cpp +4 -3
  20. data/GosuImpl/Audio/ALChannelManagement.hpp +23 -11
  21. data/GosuImpl/Audio/AudioFile.hpp +11 -3
  22. data/GosuImpl/Audio/AudioOpenAL.cpp +613 -0
  23. data/GosuImpl/Audio/AudioOpenAL.mm +1 -605
  24. data/GosuImpl/Audio/AudioSDL.cpp +12 -14
  25. data/GosuImpl/Audio/AudioToolboxFile.hpp +0 -1
  26. data/GosuImpl/Audio/OggFile.hpp +2 -0
  27. data/GosuImpl/Audio/SndFile.hpp +158 -0
  28. data/GosuImpl/DirectoriesWin.cpp +18 -18
  29. data/GosuImpl/Graphics/BitmapApple.mm +17 -19
  30. data/GosuImpl/Graphics/BitmapBMP.cpp +7 -2
  31. data/GosuImpl/Graphics/BitmapFreeImage.cpp +11 -12
  32. data/GosuImpl/Graphics/BitmapGDIplus.cpp +35 -31
  33. data/GosuImpl/Graphics/BitmapUtils.cpp +1 -1
  34. data/GosuImpl/Graphics/BlockAllocator.cpp +7 -8
  35. data/GosuImpl/Graphics/BlockAllocator.hpp +3 -4
  36. data/GosuImpl/Graphics/Common.hpp +3 -2
  37. data/GosuImpl/Graphics/DrawOp.hpp +2 -3
  38. data/GosuImpl/Graphics/DrawOpQueue.hpp +28 -20
  39. data/GosuImpl/Graphics/Font.cpp +13 -13
  40. data/GosuImpl/Graphics/FormattedString.hpp +93 -86
  41. data/GosuImpl/Graphics/Graphics.cpp +16 -14
  42. data/GosuImpl/Graphics/Image.cpp +7 -3
  43. data/GosuImpl/Graphics/LargeImageData.hpp +4 -5
  44. data/GosuImpl/Graphics/Macro.hpp +11 -11
  45. data/GosuImpl/Graphics/RenderState.hpp +5 -4
  46. data/GosuImpl/Graphics/TexChunk.cpp +3 -3
  47. data/GosuImpl/Graphics/TexChunk.hpp +4 -4
  48. data/GosuImpl/Graphics/Text.cpp +29 -30
  49. data/GosuImpl/Graphics/TextMac.cpp +9 -7
  50. data/GosuImpl/Graphics/TextTTFWin.cpp +3 -1
  51. data/GosuImpl/Graphics/TextTouch.mm +0 -1
  52. data/GosuImpl/Graphics/TextUnix.cpp +12 -4
  53. data/GosuImpl/Graphics/TextWin.cpp +4 -2
  54. data/GosuImpl/Graphics/Texture.cpp +7 -6
  55. data/GosuImpl/Graphics/Texture.hpp +3 -4
  56. data/GosuImpl/InputMac.mm +12 -15
  57. data/GosuImpl/InputTouch.mm +3 -3
  58. data/GosuImpl/InputWin.cpp +149 -159
  59. data/GosuImpl/InputX.cpp +0 -0
  60. data/GosuImpl/MacUtility.hpp +9 -4
  61. data/GosuImpl/RubyGosu.swg +38 -43
  62. data/GosuImpl/RubyGosu_wrap.cxx +89 -96
  63. data/GosuImpl/Sockets/CommSocket.cpp +5 -5
  64. data/GosuImpl/Sockets/Sockets.hpp +4 -4
  65. data/GosuImpl/TimingApple.cpp +2 -3
  66. data/GosuImpl/Utility.cpp +18 -0
  67. data/GosuImpl/WinMain.cpp +0 -1
  68. data/GosuImpl/WinUtility.cpp +2 -2
  69. data/GosuImpl/WindowMac.mm +20 -17
  70. data/GosuImpl/WindowTouch.mm +8 -7
  71. data/GosuImpl/WindowWin.cpp +12 -7
  72. data/GosuImpl/WindowX.cpp +67 -18
  73. data/lib/gosu.rb +14 -12
  74. data/linux/extconf.rb +11 -6
  75. metadata +8 -7
  76. data/GosuImpl/Audio/AudioAudiere.cpp +0 -448
  77. data/GosuImpl/RubyGosu_DllMain.cxx +0 -31
@@ -1,605 +1 @@
1
- #include <GosuImpl/MacUtility.hpp>
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>