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.
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>