gosu 0.7.26.1 → 0.7.27

Sign up to get free protection for your applications and to get access to all the features.
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];