gosu 0.7.26.1 → 0.7.27

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/COPYING.txt CHANGED
@@ -26,5 +26,6 @@ http://www.libgosu.org/
26
26
 
27
27
  ***
28
28
 
29
- This does NOT apply to fmod.dll shipped with the Windows version of Gosu.
30
- FMOD is a property of Firelight Technologies Pty, Ltd., see www.fmod.org.
29
+ This does NOT apply to audiere.dll shipped with the Windows versions of
30
+ Gosu. Audiere is a separate library licensed under the Lesser General
31
+ Public License. Please consult audiere.sf.net for more details.
data/Gosu/Audio.hpp CHANGED
@@ -96,8 +96,10 @@ namespace Gosu
96
96
 
97
97
 
98
98
  // Deprecated.
99
- Sample(Audio& audio, const std::wstring& filename);
100
- Sample(Audio& audio, Reader reader);
99
+ #ifndef SWIG
100
+ GOSU_DEPRECATED Sample(Audio& audio, const std::wstring& filename);
101
+ GOSU_DEPRECATED Sample(Audio& audio, Reader reader);
102
+ #endif
101
103
  };
102
104
 
103
105
  //! Songs are less flexible than samples in that they can only be played
@@ -110,14 +112,6 @@ namespace Gosu
110
112
  boost::scoped_ptr<BaseData> data;
111
113
 
112
114
  public:
113
- //! There are two types of songs that can be loaded as a Song: Streamed
114
- //! songs (like OGG) and modules (like MOD or XM).
115
- enum Type
116
- {
117
- stStream,
118
- stModule
119
- };
120
-
121
115
  //! Constructs a song that can be played on the provided audio system
122
116
  //! and loads the song from a file. The type is determined from the
123
117
  //! filename.
@@ -125,7 +119,7 @@ namespace Gosu
125
119
 
126
120
  //! Constructs a song of the specified type that can be played on the
127
121
  //! provided audio system and loads the song data from a stream.
128
- Song(Type type, Reader reader);
122
+ explicit Song(Reader reader);
129
123
 
130
124
  ~Song();
131
125
 
@@ -157,8 +151,18 @@ namespace Gosu
157
151
  static void update();
158
152
 
159
153
  // Deprecated.
160
- Song(Audio&, const std::wstring& filename);
161
- Song(Audio&, Type type, Reader reader);
154
+ #ifndef SWIG
155
+ //! There are two types of songs that can be loaded as a Song: Streamed
156
+ //! songs (like OGG) and modules (like MOD or XM).
157
+ enum Type
158
+ {
159
+ stStream,
160
+ stModule
161
+ };
162
+
163
+ GOSU_DEPRECATED Song(Audio&, const std::wstring& filename);
164
+ GOSU_DEPRECATED Song(Audio&, Type type, Reader reader);
165
+ #endif
162
166
  };
163
167
  }
164
168
 
data/Gosu/Gosu.hpp CHANGED
@@ -19,6 +19,7 @@
19
19
  #include <Gosu/Image.hpp>
20
20
  #include <Gosu/ImageData.hpp>
21
21
  #include <Gosu/Input.hpp>
22
+ #include <Gosu/Inspection.hpp>
22
23
  #include <Gosu/IO.hpp>
23
24
  #include <Gosu/Math.hpp>
24
25
  #include <Gosu/Platform.hpp>
@@ -0,0 +1,14 @@
1
+ //! \file Inspection.hpp
2
+ //! A special set of functions designed for tuning Gosu games.
3
+
4
+ #ifndef GOSU_INSPECTION_HPP
5
+ #define GOSU_INSPECTION_HPP
6
+
7
+ namespace Gosu
8
+ {
9
+ //! Returns the current framerate, as determined by an unspecified and possibly
10
+ //! horrible algorithm.
11
+ int fps();
12
+ }
13
+
14
+ #endif
data/Gosu/Version.hpp CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  #define GOSU_MAJOR_VERSION 0
5
5
  #define GOSU_MINOR_VERSION 7
6
- #define GOSU_POINT_VERSION 26
7
- #define GOSU_VERSION "0.7.26.1"
6
+ #define GOSU_POINT_VERSION 27
7
+ #define GOSU_VERSION "0.7.27"
8
8
 
9
9
  #endif
@@ -0,0 +1,443 @@
1
+ #include <Gosu/Audio.hpp>
2
+ #include <Gosu/Math.hpp>
3
+ #include <Gosu/IO.hpp>
4
+ #include <boost/foreach.hpp>
5
+ #include <algorithm>
6
+ #include <stdexcept>
7
+ #include <vector>
8
+
9
+ #include <audiere.h>
10
+ using namespace audiere;
11
+
12
+ namespace Gosu
13
+ {
14
+ namespace
15
+ {
16
+ Song* curSong = 0;
17
+
18
+ // Gosu::Buffer-based implementation of Audiere's File interface.
19
+ // Provided since Audiere uses stdio to open files, which may not support Unicode
20
+ // filenames outside of the current codepage on Windows(?).
21
+ class MemoryBuffer : boost::noncopyable
22
+ {
23
+ Gosu::Buffer buffer;
24
+ FilePtr file;
25
+
26
+ public:
27
+ MemoryBuffer(Gosu::Reader reader)
28
+ {
29
+ buffer.resize(reader.resource().size() - reader.position());
30
+ reader.read(buffer.data(), buffer.size());
31
+ file = audiere::CreateMemoryFile(buffer.data(), buffer.size());
32
+ }
33
+
34
+ MemoryBuffer(const std::wstring& filename)
35
+ {
36
+ Gosu::loadFile(buffer, filename);
37
+ file = audiere::CreateMemoryFile(buffer.data(), buffer.size());
38
+ }
39
+
40
+ operator const FilePtr&()
41
+ {
42
+ return file;
43
+ }
44
+ };
45
+
46
+ class StreamRegistry : public RefImplementation<StopCallback>, boost::noncopyable
47
+ {
48
+ struct NumberedStream
49
+ {
50
+ int extra;
51
+ OutputStreamPtr stream;
52
+ };
53
+ std::vector<NumberedStream> streams;
54
+
55
+ ADR_METHOD(void) streamStopped(StopEvent* event)
56
+ {
57
+ if (event->getReason() == StopEvent::STREAM_ENDED)
58
+ if (!clear(event->getOutputStream()) && curSong)
59
+ curSong = 0;
60
+ }
61
+
62
+ public:
63
+ StreamRegistry()
64
+ {
65
+ streams.reserve(100);
66
+ }
67
+
68
+ OutputStreamPtr get(int handle, int extra) const
69
+ {
70
+ if (handle < streams.size() && streams[handle].extra == extra)
71
+ return streams[handle].stream;
72
+ return OutputStreamPtr();
73
+ }
74
+
75
+ void put(OutputStreamPtr stream, int& handle, int& extra)
76
+ {
77
+ handle = 0;
78
+ for (handle; handle < streams.size(); ++handle)
79
+ if (!streams[handle].stream)
80
+ {
81
+ streams[handle].stream = stream;
82
+ extra = ++streams[handle].extra;
83
+ return;
84
+ }
85
+ // handle == streams.size() <3
86
+ NumberedStream newStream = { extra = 0, stream };
87
+ streams.push_back(newStream);
88
+ }
89
+
90
+ void clear(int handle)
91
+ {
92
+ streams.at(handle).stream = 0;
93
+ }
94
+
95
+ bool clear(OutputStreamPtr stream)
96
+ {
97
+ BOOST_FOREACH (NumberedStream& numberedStream, streams)
98
+ if (numberedStream.stream == stream)
99
+ {
100
+ numberedStream.stream = 0;
101
+ return true;
102
+ }
103
+ return false;
104
+ }
105
+ };
106
+
107
+ // Intentionally leak. Let Windows clean up on program exit.
108
+ StreamRegistry& streams = *(new StreamRegistry);
109
+
110
+ // Since audiere::OpenDevice is (contains) the first call to audiere.dll, we wrap
111
+ // the call in error handling code to see if the lazily linked DLL is there.
112
+ bool getDevice(AudioDevice*& device)
113
+ {
114
+ #ifdef GOSU_IS_WIN
115
+ // Copied and pasted from MSDN.
116
+ #define FACILITY_VISUALCPP ((LONG)0x6d)
117
+ #define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
118
+ #define BAD_MOD VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
119
+
120
+ __try
121
+ {
122
+ #endif
123
+ return (device = OpenDevice());
124
+ #ifdef GOSU_IS_WIN
125
+ }
126
+ __except ((GetExceptionCode() == BAD_MOD) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
127
+ {
128
+ return false;
129
+ }
130
+ #undef BAD_MOD
131
+ #undef VcppException
132
+ #undef FACILITY_VISUALCPP
133
+ #endif
134
+ }
135
+
136
+ AudioDevice* device()
137
+ {
138
+ static AudioDevice* device = 0;
139
+ if (device == 0)
140
+ {
141
+ if (!getDevice(device))
142
+ throw std::runtime_error("Could not initialize audiere or library not found");
143
+
144
+ device->registerCallback(&streams);
145
+
146
+ // Never free. Especially important in Ruby version, where GC order is undefined
147
+ device->ref();
148
+ }
149
+ return device;
150
+ }
151
+
152
+ }
153
+ }
154
+
155
+ Gosu::SampleInstance::SampleInstance(int handle, int extra)
156
+ : handle(handle), extra(extra)
157
+ {
158
+ }
159
+
160
+ bool Gosu::SampleInstance::playing() const
161
+ {
162
+ OutputStreamPtr stream = streams.get(handle, extra);
163
+ return stream && stream->isPlaying();
164
+ }
165
+
166
+ bool Gosu::SampleInstance::paused() const
167
+ {
168
+ OutputStreamPtr stream = streams.get(handle, extra);
169
+ return stream && !stream->isPlaying();
170
+ }
171
+
172
+ void Gosu::SampleInstance::pause()
173
+ {
174
+ if (OutputStreamPtr stream = streams.get(handle, extra))
175
+ stream->stop();
176
+ }
177
+
178
+ void Gosu::SampleInstance::resume()
179
+ {
180
+ if (OutputStreamPtr stream = streams.get(handle, extra))
181
+ stream->play();
182
+ }
183
+
184
+ void Gosu::SampleInstance::stop()
185
+ {
186
+ if (OutputStreamPtr stream = streams.get(handle, extra))
187
+ stream->stop(), streams.clear(handle);
188
+ }
189
+
190
+ void Gosu::SampleInstance::changeVolume(double volume)
191
+ {
192
+ if (OutputStreamPtr stream = streams.get(handle, extra))
193
+ stream->setVolume(volume);
194
+ }
195
+
196
+ void Gosu::SampleInstance::changePan(double pan)
197
+ {
198
+ if (OutputStreamPtr stream = streams.get(handle, extra))
199
+ stream->setPan(clamp<float>(pan, -1.f, +1.f));
200
+ }
201
+
202
+ void Gosu::SampleInstance::changeSpeed(double speed)
203
+ {
204
+ if (OutputStreamPtr stream = streams.get(handle, extra))
205
+ stream->setPitchShift(clamp<float>(speed, 0.5f, 2.0f));
206
+ }
207
+
208
+ struct Gosu::Sample::SampleData : boost::noncopyable
209
+ {
210
+ SampleBufferPtr buffer;
211
+ };
212
+
213
+ Gosu::Sample::Sample(const std::wstring& filename)
214
+ : data(new SampleData)
215
+ {
216
+ device(); // Implicitly open audio device
217
+
218
+ SampleSourcePtr source = OpenSampleSource(MemoryBuffer(filename), FF_AUTODETECT);
219
+ data->buffer = CreateSampleBuffer(source);
220
+ }
221
+
222
+ Gosu::Sample::Sample(Reader reader)
223
+ {
224
+ device(); // Implicitly open audio device
225
+
226
+ SampleSourcePtr source = audiere::OpenSampleSource(MemoryBuffer(reader), FF_AUTODETECT);
227
+ data->buffer = CreateSampleBuffer(source);
228
+ }
229
+
230
+ Gosu::SampleInstance Gosu::Sample::play(double volume, double speed,
231
+ bool looping) const
232
+ {
233
+ OutputStreamPtr stream = device()->openStream(data->buffer->openStream());
234
+ int handle, extra;
235
+ streams.put(stream, handle, extra);
236
+
237
+ SampleInstance instance(handle, extra);
238
+ instance.changeVolume(volume);
239
+ instance.changeSpeed(speed);
240
+ stream->setRepeat(looping);
241
+ stream->play();
242
+ return instance;
243
+ }
244
+
245
+ Gosu::SampleInstance Gosu::Sample::playPan(double pan, double volume,
246
+ double speed, bool looping) const
247
+ {
248
+ OutputStreamPtr stream = device()->openStream(data->buffer->openStream());
249
+ int handle, extra;
250
+ streams.put(stream, handle, extra);
251
+
252
+ SampleInstance instance(handle, extra);
253
+ instance.changePan(pan);
254
+ instance.changeVolume(volume);
255
+ instance.changeSpeed(speed);
256
+ stream->setRepeat(looping);
257
+ stream->play();
258
+ return instance;
259
+ }
260
+
261
+ class Gosu::Song::BaseData : boost::noncopyable
262
+ {
263
+ double volume_;
264
+
265
+ protected:
266
+ BaseData() : volume_(1) {}
267
+ virtual void applyVolume() = 0;
268
+
269
+ public:
270
+ virtual ~BaseData() {}
271
+
272
+ virtual void play(bool looping) = 0;
273
+ virtual bool playing() const = 0;
274
+ virtual void pause() = 0;
275
+ virtual void stop() = 0;
276
+
277
+ double volume() const
278
+ {
279
+ return volume_;
280
+ }
281
+
282
+ void changeVolume(double volume)
283
+ {
284
+ volume_ = clamp(volume, 0.0, 1.0);
285
+ applyVolume();
286
+ }
287
+ };
288
+
289
+ class Gosu::Song::StreamData : public BaseData
290
+ {
291
+ MemoryBuffer buffer;
292
+ OutputStreamPtr stream;
293
+ SampleInstance instance;
294
+ bool loop;
295
+
296
+ void init()
297
+ {
298
+ int handle, extra;
299
+ stream = OpenSound(device(), buffer, true);
300
+ streams.put(stream, handle, extra);
301
+ instance = SampleInstance(handle, extra);
302
+ loop = false;
303
+ }
304
+
305
+ public:
306
+ StreamData(Gosu::Reader reader)
307
+ : buffer(reader), instance(-1, -1)
308
+ {
309
+ init();
310
+ }
311
+
312
+ StreamData(const std::wstring& filename)
313
+ : buffer(filename), instance(-1, -1)
314
+ {
315
+ init();
316
+ }
317
+
318
+ void play(bool looping)
319
+ {
320
+ applyVolume();
321
+ if (looping != loop)
322
+ stream->setRepeat(loop = looping);
323
+ stream->play();
324
+ }
325
+
326
+ bool playing() const
327
+ {
328
+ return instance.playing();
329
+ }
330
+
331
+ void pause()
332
+ {
333
+ instance.pause();
334
+ }
335
+
336
+ void stop()
337
+ {
338
+ instance.pause();
339
+ stream->reset();
340
+ }
341
+
342
+ void applyVolume()
343
+ {
344
+ instance.changeVolume(volume());
345
+ }
346
+ };
347
+
348
+ Gosu::Song::Song(const std::wstring& filename)
349
+ : data(new StreamData(filename))
350
+ {
351
+ }
352
+
353
+ Gosu::Song::Song(Reader reader)
354
+ : data(new StreamData(reader))
355
+ {
356
+ }
357
+
358
+ Gosu::Song::~Song()
359
+ {
360
+ }
361
+
362
+ Gosu::Song* Gosu::Song::currentSong()
363
+ {
364
+ if (curSong)
365
+ return curSong;
366
+ return 0;
367
+ }
368
+
369
+ void Gosu::Song::play(bool looping)
370
+ {
371
+ if (Gosu::Song* cur = currentSong())
372
+ if (cur != this)
373
+ {
374
+ cur->stop();
375
+ assert (currentSong() == 0);
376
+ }
377
+
378
+ data->play(looping); // May be redundant
379
+ curSong = this; // May be redundant
380
+ }
381
+
382
+ void Gosu::Song::pause()
383
+ {
384
+ if (curSong == this && data->playing())
385
+ data->pause();
386
+ }
387
+
388
+ bool Gosu::Song::paused() const
389
+ {
390
+ return curSong == this && !data->playing();
391
+ }
392
+
393
+ void Gosu::Song::stop()
394
+ {
395
+ if (curSong == this)
396
+ {
397
+ data->stop();
398
+ curSong = 0;
399
+ }
400
+ }
401
+
402
+ bool Gosu::Song::playing() const
403
+ {
404
+ assert (!(curSong != this && data->playing()));
405
+ return data->playing();
406
+ }
407
+
408
+ double Gosu::Song::volume() const
409
+ {
410
+ return data->volume();
411
+ }
412
+
413
+ void Gosu::Song::changeVolume(double volume)
414
+ {
415
+ data->changeVolume(volume);
416
+ }
417
+
418
+ void Gosu::Song::update()
419
+ {
420
+ device()->update();
421
+ }
422
+
423
+ // Deprecated constructors.
424
+
425
+ Gosu::Sample::Sample(Audio& audio, const std::wstring& filename)
426
+ {
427
+ Sample(filename).data.swap(data);
428
+ }
429
+
430
+ Gosu::Sample::Sample(Audio& audio, Reader reader)
431
+ {
432
+ Sample(reader).data.swap(data);
433
+ }
434
+
435
+ Gosu::Song::Song(Audio& audio, const std::wstring& filename)
436
+ {
437
+ Song(filename).data.swap(data);
438
+ }
439
+
440
+ Gosu::Song::Song(Audio& audio, Type type, Reader reader)
441
+ {
442
+ Song(reader).data.swap(data);
443
+ }
@@ -506,7 +506,7 @@ Gosu::Song::Song(const std::wstring& filename)
506
506
  }
507
507
  }
508
508
 
509
- Gosu::Song::Song(Type type, Reader reader)
509
+ Gosu::Song::Song(Reader reader)
510
510
  {
511
511
  CONSTRUCTOR_COMMON;
512
512
 
@@ -601,5 +601,5 @@ Gosu::Song::Song(Audio& audio, const std::wstring& filename)
601
601
 
602
602
  Gosu::Song::Song(Audio& audio, Type type, Reader reader)
603
603
  {
604
- Song(type, reader).data.swap(data);
604
+ Song(reader).data.swap(data);
605
605
  }
@@ -208,7 +208,7 @@ Gosu::Song::Song(const std::wstring& filename)
208
208
  Mix_HookMusicFinished(BaseData::endSongCallback);
209
209
  }
210
210
 
211
- Gosu::Song::Song(Type type, Reader reader)
211
+ Gosu::Song::Song(Reader reader)
212
212
  : data(new BaseData)
213
213
  {
214
214
  requireSDLMixer();
@@ -53,7 +53,7 @@ Gosu::Color Gosu::Color::fromAHSV(Channel alpha, double h, double s, double v)
53
53
  return Color(alpha, v * 255, v * 255, v * 255);
54
54
 
55
55
  // Normalize hue
56
- h = ((static_cast<int>(h) % 360) + 360) % 360;
56
+ h = normalizeAngle(h);
57
57
 
58
58
  int sector = h / 60;
59
59
  double factorial = h / 60 - sector;
@@ -8,6 +8,14 @@
8
8
 
9
9
  Gosu::Window& windowInstance();
10
10
 
11
+ namespace Gosu
12
+ {
13
+ namespace FPS
14
+ {
15
+ void registerFrame();
16
+ }
17
+ }
18
+
11
19
  int Gosu::clipRectBaseFactor()
12
20
  {
13
21
  static int result = 0;
@@ -46,7 +54,6 @@ int Gosu::clipRectBaseFactor()
46
54
 
47
55
  @end
48
56
 
49
-
50
57
  @implementation GosuView
51
58
 
52
59
  @synthesize context;
@@ -78,6 +85,8 @@ int Gosu::clipRectBaseFactor()
78
85
  if (not windowInstance().needsRedraw())
79
86
  return;
80
87
 
88
+ Gosu::FPS::registerFrame();
89
+
81
90
  [EAGLContext setCurrentContext:context];
82
91
  glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
83
92
  glViewport(0, 0, backingWidth, backingHeight);
@@ -0,0 +1,27 @@
1
+ #include <Gosu/Inspection.hpp>
2
+ #include <Gosu/Timing.hpp>
3
+
4
+ namespace Gosu
5
+ {
6
+ namespace FPS
7
+ {
8
+ int fps, accum, sec;
9
+
10
+ void registerFrame()
11
+ {
12
+ ++accum;
13
+ int newSec = Gosu::milliseconds() / 1000;
14
+ if (sec != newSec)
15
+ {
16
+ sec = newSec;
17
+ fps = accum;
18
+ accum = 0;
19
+ }
20
+ }
21
+ }
22
+
23
+ int fps()
24
+ {
25
+ return FPS::fps;
26
+ }
27
+ }
@@ -158,6 +158,7 @@
158
158
  #include <Gosu/Graphics.hpp>
159
159
  #include <Gosu/Image.hpp>
160
160
  #include <Gosu/ImageData.hpp>
161
+ #include <Gosu/Inspection.hpp>
161
162
  #include <Gosu/Input.hpp>
162
163
  #include <Gosu/IO.hpp>
163
164
  #include <Gosu/Math.hpp>
@@ -501,6 +502,11 @@ namespace Gosu {
501
502
  }
502
503
  }
503
504
 
505
+ // Inspection:
506
+
507
+ %include "../Gosu/Inspection.hpp"
508
+
509
+
504
510
  // Audio:
505
511
 
506
512
  %ignore Gosu::Audio;
@@ -510,7 +516,7 @@ namespace Gosu {
510
516
  %ignore Gosu::Sample::Sample(Reader reader);
511
517
  %ignore Gosu::Song::Song(Audio& audio, const std::wstring& filename);
512
518
  %ignore Gosu::Song::Song(Audio& audio, Type type, Reader reader);
513
- %ignore Gosu::Song::Song(Type type, Reader reader);
519
+ %ignore Gosu::Song::Song(Reader reader);
514
520
  %rename("playing?") playing;
515
521
  %rename("paused?") paused;
516
522
  %rename("volume=") changeVolume;
@@ -4,8 +4,9 @@ using namespace std;
4
4
 
5
5
  BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
6
6
  {
7
- // Append .so parent folder to PATH to make extensions (e.g. FMOD.dll) loadable.
8
-
7
+ // Append .so parent folder to PATH to make extensions (e.g. audiere.dll) loadable.
8
+ // TODO: This sounds like a risky thing wrt security, but does this matter?
9
+
9
10
  if (fdwReason == DLL_PROCESS_ATTACH)
10
11
  {
11
12
  TCHAR buffer[MAX_PATH+1];