rubygame 2.3.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/CREDITS +60 -0
  2. data/LICENSE +504 -0
  3. data/NEWS +252 -0
  4. data/README +123 -0
  5. data/ROADMAP +109 -0
  6. data/Rakefile +440 -0
  7. data/doc/extended_readme.rdoc +49 -0
  8. data/doc/getting_started.rdoc +47 -0
  9. data/doc/macosx_install.rdoc +70 -0
  10. data/doc/windows_install.rdoc +123 -0
  11. data/ext/rubygame/rubygame_core.so +0 -0
  12. data/ext/rubygame/rubygame_event.c +644 -0
  13. data/ext/rubygame/rubygame_event.h +48 -0
  14. data/ext/rubygame/rubygame_event.obj +0 -0
  15. data/ext/rubygame/rubygame_gfx.c +942 -0
  16. data/ext/rubygame/rubygame_gfx.h +101 -0
  17. data/ext/rubygame/rubygame_gfx.obj +0 -0
  18. data/ext/rubygame/rubygame_gfx.so +0 -0
  19. data/ext/rubygame/rubygame_gl.c +154 -0
  20. data/ext/rubygame/rubygame_gl.h +32 -0
  21. data/ext/rubygame/rubygame_gl.obj +0 -0
  22. data/ext/rubygame/rubygame_image.c +252 -0
  23. data/ext/rubygame/rubygame_image.h +41 -0
  24. data/ext/rubygame/rubygame_image.obj +0 -0
  25. data/ext/rubygame/rubygame_image.so +0 -0
  26. data/ext/rubygame/rubygame_joystick.c +247 -0
  27. data/ext/rubygame/rubygame_joystick.h +41 -0
  28. data/ext/rubygame/rubygame_joystick.obj +0 -0
  29. data/ext/rubygame/rubygame_main.c +155 -0
  30. data/ext/rubygame/rubygame_main.h +36 -0
  31. data/ext/rubygame/rubygame_main.obj +0 -0
  32. data/ext/rubygame/rubygame_mixer.c +1024 -0
  33. data/ext/rubygame/rubygame_mixer.h +36 -0
  34. data/ext/rubygame/rubygame_mixer.obj +0 -0
  35. data/ext/rubygame/rubygame_mixer.so +0 -0
  36. data/ext/rubygame/rubygame_music.c +1017 -0
  37. data/ext/rubygame/rubygame_music.h +29 -0
  38. data/ext/rubygame/rubygame_music.obj +0 -0
  39. data/ext/rubygame/rubygame_screen.c +448 -0
  40. data/ext/rubygame/rubygame_screen.h +43 -0
  41. data/ext/rubygame/rubygame_screen.obj +0 -0
  42. data/ext/rubygame/rubygame_shared.c +272 -0
  43. data/ext/rubygame/rubygame_shared.h +68 -0
  44. data/ext/rubygame/rubygame_shared.obj +0 -0
  45. data/ext/rubygame/rubygame_sound.c +863 -0
  46. data/ext/rubygame/rubygame_sound.h +29 -0
  47. data/ext/rubygame/rubygame_sound.obj +0 -0
  48. data/ext/rubygame/rubygame_surface.c +1151 -0
  49. data/ext/rubygame/rubygame_surface.h +62 -0
  50. data/ext/rubygame/rubygame_surface.obj +0 -0
  51. data/ext/rubygame/rubygame_time.c +183 -0
  52. data/ext/rubygame/rubygame_time.h +32 -0
  53. data/ext/rubygame/rubygame_time.obj +0 -0
  54. data/ext/rubygame/rubygame_ttf.c +599 -0
  55. data/ext/rubygame/rubygame_ttf.h +69 -0
  56. data/ext/rubygame/rubygame_ttf.obj +0 -0
  57. data/ext/rubygame/rubygame_ttf.so +0 -0
  58. data/lib/rubygame.rb +41 -0
  59. data/lib/rubygame/clock.rb +128 -0
  60. data/lib/rubygame/color.rb +79 -0
  61. data/lib/rubygame/color/models/base.rb +111 -0
  62. data/lib/rubygame/color/models/hsl.rb +153 -0
  63. data/lib/rubygame/color/models/hsv.rb +149 -0
  64. data/lib/rubygame/color/models/rgb.rb +78 -0
  65. data/lib/rubygame/color/palettes/css.rb +49 -0
  66. data/lib/rubygame/color/palettes/palette.rb +100 -0
  67. data/lib/rubygame/color/palettes/x11.rb +177 -0
  68. data/lib/rubygame/constants.rb +238 -0
  69. data/lib/rubygame/event.rb +313 -0
  70. data/lib/rubygame/ftor.rb +370 -0
  71. data/lib/rubygame/hotspot.rb +265 -0
  72. data/lib/rubygame/keyconstants.rb +237 -0
  73. data/lib/rubygame/mediabag.rb +94 -0
  74. data/lib/rubygame/named_resource.rb +254 -0
  75. data/lib/rubygame/queue.rb +288 -0
  76. data/lib/rubygame/rect.rb +612 -0
  77. data/lib/rubygame/sfont.rb +223 -0
  78. data/lib/rubygame/sprite.rb +511 -0
  79. data/samples/FreeSans.ttf +0 -0
  80. data/samples/GPL.txt +340 -0
  81. data/samples/README +40 -0
  82. data/samples/chimp.bmp +0 -0
  83. data/samples/chimp.rb +302 -0
  84. data/samples/demo_gl.rb +151 -0
  85. data/samples/demo_gl_tex.rb +197 -0
  86. data/samples/demo_music.rb +77 -0
  87. data/samples/demo_rubygame.rb +296 -0
  88. data/samples/demo_sfont.rb +52 -0
  89. data/samples/demo_ttf.rb +193 -0
  90. data/samples/demo_utf8.rb +53 -0
  91. data/samples/fist.bmp +0 -0
  92. data/samples/load_and_blit.rb +22 -0
  93. data/samples/panda.png +0 -0
  94. data/samples/punch.wav +0 -0
  95. data/samples/ruby.png +0 -0
  96. data/samples/song.ogg +0 -0
  97. data/samples/term16.png +0 -0
  98. data/samples/whiff.wav +0 -0
  99. metadata +164 -0
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
+ * Copyright (C) 2004-2007 John Croisant
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+ #ifndef _RUBYGAME_SCREEN_H
22
+ #define _RUBYGAME_SCREEN_H
23
+
24
+ extern void Rubygame_Init_Screen();
25
+
26
+ extern VALUE cScreen;
27
+
28
+ extern VALUE rbgm_screen_setmode(int, VALUE*, VALUE);
29
+ extern VALUE rbgm_screen_getsurface(VALUE);
30
+
31
+ extern VALUE rbgm_screen_getcaption(VALUE);
32
+ extern VALUE rbgm_screen_setcaption(VALUE, VALUE);
33
+
34
+ extern VALUE rbgm_screen_seticon(VALUE, VALUE);
35
+
36
+ extern VALUE rbgm_screen_update(int, VALUE*, VALUE);
37
+ extern VALUE rbgm_screen_updaterects(VALUE, VALUE);
38
+ extern VALUE rbgm_screen_flip(VALUE);
39
+
40
+ extern VALUE rbgm_screen_getshowcursor(VALUE);
41
+ extern VALUE rbgm_screen_setshowcursor(VALUE, VALUE);
42
+
43
+ #endif
Binary file
@@ -0,0 +1,272 @@
1
+ /*
2
+ * Code that is common to all Rubygame modules.
3
+ *--
4
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
+ * Copyright (C) 2004-2007 John Croisant
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ *++
21
+ */
22
+
23
+ #include "rubygame_shared.h"
24
+
25
+ VALUE mRubygame;
26
+ VALUE cSurface;
27
+ VALUE cRect;
28
+ VALUE eSDLError;
29
+ VALUE mNamedResource;
30
+
31
+
32
+ SDL_Rect *make_rect(int, int, int, int);
33
+ SDL_Color make_sdl_color(VALUE);
34
+ int init_video_system();
35
+ void Init_rubygame_shared();
36
+
37
+ SDL_Rect *make_rect(int x, int y, int w, int h)
38
+ {
39
+ SDL_Rect *rect;
40
+ rect = (SDL_Rect *) malloc(sizeof(SDL_Rect));
41
+ rect->x = x;
42
+ rect->y = y;
43
+ rect->w = w;
44
+ rect->h = h;
45
+ return rect;
46
+ }
47
+
48
+ /* Returns a symbol from the given char* string */
49
+ VALUE make_symbol(char *string)
50
+ {
51
+ return ID2SYM(rb_intern(string));
52
+ }
53
+
54
+ /* Returns a char* string from the given symbol */
55
+ char *unmake_symbol(VALUE symbol)
56
+ {
57
+ return rb_id2name( SYM2ID(symbol) );
58
+ }
59
+
60
+
61
+ /* Lowercase, change spaces to underscores, and convert to symbol.
62
+ * Equivalent to: str.downcase!.gsub!(" ","_").intern
63
+ */
64
+ VALUE sanitized_symbol(char *string)
65
+ {
66
+ VALUE str = rb_str_new2(string);
67
+
68
+ rb_funcall( str, rb_intern("downcase!"), 0 );
69
+ rb_funcall( str, rb_intern("gsub!"), 2, rb_str_new2(" "), rb_str_new2("_") );
70
+ return rb_funcall( str, rb_intern("intern"), 0 );
71
+ }
72
+
73
+ /* Take either nil, Numeric or an Array of Numerics, returns Uint32. */
74
+ Uint32 collapse_flags(VALUE vflags)
75
+ {
76
+ Uint32 flags = 0;
77
+ int i;
78
+
79
+ if( RTEST(vflags) )
80
+ {
81
+ switch( TYPE(vflags) ){
82
+ case T_ARRAY: {
83
+ int len = RARRAY(vflags)->len;
84
+ for(i=0; i < len; i++)
85
+ {
86
+ flags |= NUM2UINT( rb_ary_entry( vflags,i ) );
87
+ }
88
+ break;
89
+ }
90
+ case T_BIGNUM: {
91
+ flags = rb_big2uint( vflags );
92
+ break;
93
+ }
94
+ case T_FIXNUM: {
95
+ flags = NUM2UINT( vflags );
96
+ break;
97
+ }
98
+ default: {
99
+ rb_raise(rb_eArgError,"Wrong type for argument `flags' (wanted Number or Array).");
100
+ }
101
+ }
102
+ }
103
+
104
+ return flags;
105
+ }
106
+
107
+ VALUE convert_to_array(VALUE val)
108
+ {
109
+ VALUE v = rb_check_array_type(val);
110
+ if( TYPE(v) != T_ARRAY )
111
+ {
112
+ rb_raise(rb_eTypeError, "can't convert %s into Array",
113
+ rb_obj_classname(val));
114
+ }
115
+ return v;
116
+ }
117
+
118
+ /* Takes a Color, Array, or color name (Symbol or String).
119
+ * Returns an RGBA Array, or raises eTypeError if it can't.
120
+ */
121
+ VALUE convert_color(VALUE color)
122
+ {
123
+ if( rb_respond_to(color, rb_intern("to_sdl_rgba_ary")) )
124
+ {
125
+ return rb_funcall( color, rb_intern("to_sdl_rgba_ary"), 0 );
126
+ }
127
+ else if( rb_respond_to(color, rb_intern("to_ary")) )
128
+ {
129
+ return convert_to_array( color );
130
+ }
131
+ else if( TYPE(color) == T_SYMBOL || TYPE(color) == T_STRING )
132
+ {
133
+ VALUE mColor = rb_const_get( mRubygame, rb_intern("Color") );
134
+ return convert_color( rb_funcall( mColor, rb_intern("[]"), 1, color) );
135
+ }
136
+ else
137
+ {
138
+ rb_raise(rb_eTypeError, "unsupported type %s for color",
139
+ rb_obj_classname(color));
140
+ }
141
+ }
142
+
143
+ SDL_Color make_sdl_color(VALUE vcolor)
144
+ {
145
+ SDL_Color color;
146
+ vcolor = convert_color(vcolor);
147
+ extract_rgb_u8_as_u8(vcolor, &(color.r), &(color.g), &(color.b));
148
+ return color;
149
+ }
150
+
151
+ void extract_rgb_u8_as_u8(VALUE color, Uint8 *r, Uint8 *g, Uint8 *b)
152
+ {
153
+ *r = NUM2UINT(rb_ary_entry(color, 0));
154
+ *g = NUM2UINT(rb_ary_entry(color, 1));
155
+ *b = NUM2UINT(rb_ary_entry(color, 2));
156
+ }
157
+
158
+ void extract_rgba_u8_as_u8(VALUE color, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
159
+ {
160
+ *r = NUM2UINT(rb_ary_entry(color, 0));
161
+ *g = NUM2UINT(rb_ary_entry(color, 1));
162
+ *b = NUM2UINT(rb_ary_entry(color, 2));
163
+
164
+ if( RARRAY(color)->len > 3 )
165
+ {
166
+ *a = NUM2UINT(rb_ary_entry(color, 3));
167
+ }
168
+ else
169
+ {
170
+ *a = 255;
171
+ }
172
+ }
173
+
174
+
175
+
176
+ /* --
177
+ *
178
+ * Issues a deprecation warning for the given feature/method.
179
+ *
180
+ * ++
181
+ */
182
+ void rg_deprecated( char *feature, char *version )
183
+ {
184
+ rb_warning( "%s is DEPRECATED and will be removed in Rubygame %s! "
185
+ "Please see the docs for more information.",
186
+ feature, version );
187
+ }
188
+
189
+
190
+
191
+ /* --
192
+ *
193
+ * call-seq:
194
+ * init_video_system() -> int
195
+ *
196
+ * Initialize SDL's video subsystem.
197
+ * Return 0 (zero) on success, non-zero on failure.
198
+ *
199
+ * If it has already been initialized, return 0 immediately.
200
+ *
201
+ * ++
202
+ */
203
+ int init_video_system()
204
+ {
205
+ if( SDL_WasInit(SDL_INIT_VIDEO) == 0 )
206
+ {
207
+ return SDL_Init(SDL_INIT_VIDEO);
208
+ }
209
+ else
210
+ {
211
+ return 0;
212
+ }
213
+ }
214
+
215
+ /* --
216
+ *
217
+ * Includes the Rubygame::NamedResource mixin in the given class
218
+ * and performs the `included' callback.
219
+ *
220
+ * ++
221
+ */
222
+ void rg_include_named_resource( VALUE klass )
223
+ {
224
+ /* Include the mixin, and manually perform the 'included' callback. */
225
+ rb_include_module( klass, mNamedResource );
226
+ rb_funcall( mNamedResource, rb_intern("included"), 1, klass );
227
+ }
228
+
229
+
230
+ void Init_rubygame_shared()
231
+ {
232
+
233
+ mRubygame = rb_define_module("Rubygame");
234
+
235
+ /* Rubygame::Surface class */
236
+ if( !rb_const_defined(mRubygame,rb_intern("Surface")) )
237
+ {
238
+ cSurface = rb_define_class_under(mRubygame,"Surface",rb_cObject);
239
+ }
240
+ else
241
+ {
242
+ cSurface = rb_const_get(mRubygame,rb_intern("Surface"));
243
+ }
244
+
245
+ /* Rubygame::SDLError class */
246
+ if( !rb_const_defined(mRubygame,rb_intern("SDLError")))
247
+ {
248
+ /* Indicates that an SDL function did not execute properly. */
249
+ eSDLError = rb_define_class_under(mRubygame,"SDLError",rb_eStandardError);
250
+ }
251
+ else
252
+ {
253
+ eSDLError = rb_const_get(mRubygame,rb_intern("SDLError"));
254
+ }
255
+
256
+ /* Rubygame::VERSIONS hash table */
257
+ if( !rb_const_defined(mRubygame, rb_intern("VERSIONS")))
258
+ {
259
+ /* A Hash containing the version s of rubygame and it's
260
+ * compile-time dependencies. */
261
+ rb_define_const(mRubygame,"VERSIONS",rb_hash_new());
262
+ }
263
+
264
+
265
+ /* Rubygame::NamedResource mixin. See named_resource.rb. */
266
+ if( mNamedResource == (int)NULL )
267
+ {
268
+ rb_require("rubygame/named_resource");
269
+ mNamedResource = rb_const_get(mRubygame, rb_intern("NamedResource"));
270
+ }
271
+
272
+ }
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
+ * Copyright (C) 2004-2007 John Croisant
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+ #ifndef _RUBYGAME_SHARED_H
22
+ #define _RUBYGAME_SHARED_H
23
+
24
+ #include <SDL.h>
25
+ #include <ruby.h>
26
+ #include <stdio.h>
27
+
28
+ /* General */
29
+ extern VALUE mRubygame;
30
+ extern VALUE eSDLError;
31
+ extern VALUE cSurface;
32
+ extern VALUE cRect;
33
+ extern VALUE mNamedResource;
34
+
35
+ extern SDL_Rect *make_rect(int, int, int, int);
36
+ extern VALUE make_symbol(char *);
37
+ extern char *unmake_symbol(VALUE);
38
+ extern VALUE sanitized_symbol(char *);
39
+ extern Uint32 collapse_flags(VALUE);
40
+ extern VALUE convert_to_array(VALUE);
41
+
42
+ extern SDL_Color make_sdl_color(VALUE);
43
+ extern void extract_rgb_u8_as_u8(VALUE, Uint8*, Uint8*, Uint8*);
44
+ extern void extract_rgba_u8_as_u8(VALUE, Uint8*, Uint8*, Uint8*, Uint8*);
45
+
46
+ extern void rg_deprecated( char *feature, char *version );
47
+
48
+ /* Properly includes the Rubygame::NamedResource mixin in the klass */
49
+ extern void rg_include_named_resource( VALUE klass );
50
+
51
+ extern int init_video_system();
52
+ extern void Init_rubygame_shared();
53
+
54
+ /* Apparently it is not desirable to define these functions when
55
+ * using Micrsoft Visual C.
56
+ */
57
+ #ifndef _MSC_VER
58
+
59
+ static inline int max(int a, int b) {
60
+ return a > b ? a : b;
61
+ }
62
+ static inline int min(int a, int b) {
63
+ return a > b ? b : a;
64
+ }
65
+
66
+ #endif
67
+
68
+ #endif
Binary file
@@ -0,0 +1,863 @@
1
+ /*
2
+ * Interface to SDL_mixer sound playback and mixing.
3
+ *--
4
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
+ * Copyright (C) 2004-2008 John Croisant
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ *++
21
+ */
22
+
23
+ #include "SDL_mixer.h"
24
+ #include "rubygame_shared.h"
25
+ #include "rubygame_mixer.h"
26
+
27
+ VALUE cSound;
28
+
29
+ /* A pointer to a Mix_Chunk, with a reference count.
30
+ * Allows re-use of sound data, then freeing memory when
31
+ * there are no references to it.
32
+ */
33
+ typedef struct RG_WrapChunk {
34
+ /* 'private' */
35
+ Mix_Chunk *chunk;
36
+ int ref_count;
37
+ } RG_WrapChunk;
38
+
39
+
40
+ /* The struct that the Sound class wraps. Stores a
41
+ * pointer to a RG_WrapChunk and important attributes
42
+ * of the Sound like its volume and channel it's
43
+ * playing on.
44
+ */
45
+ typedef struct RG_Sound {
46
+ /* 'public' */
47
+ float volume;
48
+
49
+ /* 'private' */
50
+ RG_WrapChunk *wrap;
51
+ int channel;
52
+ } RG_Sound;
53
+
54
+
55
+
56
+
57
+ /* Allocate/initialize the memory for a RG_WrapChunk and return a pointer. */
58
+ static RG_WrapChunk* _rg_wrapchunk_alloc()
59
+ {
60
+ RG_WrapChunk *wrap;
61
+ wrap = ALLOC(RG_WrapChunk);
62
+
63
+ wrap->chunk = NULL;
64
+ wrap->ref_count = 0;
65
+
66
+ return wrap;
67
+ }
68
+
69
+ /* Load a Mix_Chunk from a file and assign it to the RG_WrapChunk. */
70
+ static int _rg_wrapchunk_load( RG_WrapChunk *wrap, char *file )
71
+ {
72
+ /* Open audio if it's not already. Return -1 if it failed. */
73
+ if( ensure_open_audio() != 0 )
74
+ {
75
+ return -1;
76
+ }
77
+
78
+ wrap->chunk = Mix_LoadWAV( file );
79
+
80
+ if( !(wrap->chunk) )
81
+ return -1;
82
+ else
83
+ return 0;
84
+ }
85
+
86
+ /* Make a copy of the other's Mix_Chunk audio data, and assign
87
+ * it to the RG_WrapChunk.
88
+ */
89
+ static void _rg_wrapchunk_deepcopy( RG_WrapChunk *wrap, RG_WrapChunk *other )
90
+ {
91
+ *(wrap->chunk) = *(other->chunk);
92
+ }
93
+
94
+
95
+ /* Free the memory used by the RG_WrapChunk */
96
+ static void _rg_wrapchunk_free( RG_WrapChunk *wrap )
97
+ {
98
+ Mix_FreeChunk( wrap->chunk );
99
+ wrap->chunk = NULL;
100
+ free(wrap);
101
+ }
102
+
103
+
104
+
105
+
106
+ /* Associate a RG_WrapChunk with a RG_Sound. Handles reference counts. */
107
+ static inline void _rg_sound_associate( RG_Sound *sound, RG_WrapChunk *wrap )
108
+ {
109
+ sound->wrap = wrap;
110
+ sound->wrap->ref_count += 1;
111
+ }
112
+
113
+ /* Deassociate the RG_Sound's WrapChunk. Handles reference counts. */
114
+ static inline void _rg_sound_deassociate( RG_Sound *sound )
115
+ {
116
+ sound->wrap->ref_count -= 1;
117
+ sound->wrap = NULL;
118
+ }
119
+
120
+ /* Allocate/initialize the memory for a RG_Sound return a pointer. */
121
+ static RG_Sound* _rg_sound_alloc()
122
+ {
123
+ RG_Sound *sound;
124
+ sound = ALLOC(RG_Sound);
125
+
126
+ sound->wrap = NULL;
127
+ sound->volume = 1.f;
128
+ sound->channel = -1;
129
+
130
+ return sound;
131
+ }
132
+
133
+
134
+ /* Free the memory used by the Sound, and possibly the memory
135
+ * used by the WrapChunk it refers to.
136
+ */
137
+ static void _rg_sound_free( RG_Sound *sound )
138
+ {
139
+ RG_WrapChunk *wrap = sound->wrap;
140
+
141
+ _rg_sound_deassociate( sound );
142
+
143
+ free(sound);
144
+
145
+ /* If the WrapChunk has no more referrers, free it too. */
146
+ if( wrap->ref_count <= 0 )
147
+ {
148
+ _rg_wrapchunk_free( wrap );
149
+ }
150
+ }
151
+
152
+
153
+ /* Load a new Sound from a file. */
154
+ static int _rg_sound_load( RG_Sound *sound, char *file )
155
+ {
156
+ RG_WrapChunk *wrap = _rg_wrapchunk_alloc();
157
+
158
+ int result = _rg_wrapchunk_load( wrap, file );
159
+
160
+ _rg_sound_associate( sound, wrap );
161
+
162
+ return result;
163
+ }
164
+
165
+
166
+ /* Make a shallow copy of the given Sound; the new Sound points to
167
+ * the same audio data in memory as the old one. Also copies
168
+ * user-visible attributes (e.g. volume).
169
+ */
170
+ static void _rg_sound_copy( RG_Sound *sound, RG_Sound *other )
171
+ {
172
+ _rg_sound_associate( sound, other->wrap );
173
+
174
+ sound->volume = other->volume;
175
+ sound->channel = -1;
176
+ }
177
+
178
+
179
+ /* Make a new Sound with a copy of the audio from an existing Sound */
180
+ static void _rg_sound_deepcopy( RG_Sound *sound, RG_Sound *other )
181
+ {
182
+ RG_WrapChunk *wrap = _rg_wrapchunk_alloc();
183
+ _rg_wrapchunk_deepcopy( wrap, other->wrap );
184
+
185
+ _rg_sound_associate( sound, wrap );
186
+
187
+ sound->volume = other->volume;
188
+ sound->channel = -1;
189
+ }
190
+
191
+
192
+ /* Check that the given channel is (still) loaded with the given chunk. */
193
+ static int _rg_sound_channel_check( RG_Sound *sound )
194
+ {
195
+ /* channel is unset, so it doesn't belong. */
196
+ if( sound->channel == -1 )
197
+ {
198
+ return 0;
199
+ }
200
+
201
+ Mix_Chunk *chan_chunk = Mix_GetChunk(sound->channel);
202
+
203
+ /* Check that the channel chunk is the same as the given one */
204
+ return ( sound->wrap->chunk == chan_chunk );
205
+ }
206
+
207
+
208
+ /* Play the sound, fading in, repeating, and stopping as specified.
209
+ * fade_in and stop_after are in milliseconds!
210
+ */
211
+ static int _rg_sound_play( RG_Sound *sound,
212
+ int fade_in, int repeats, int stop_after )
213
+ {
214
+
215
+ /* Open audio if it's not already. Return -1 if it failed. */
216
+ if( ensure_open_audio() != 0 )
217
+ {
218
+ return -1;
219
+ }
220
+
221
+ /* If it's already playing on a channel, stop it first. */
222
+ if( _rg_sound_channel_check(sound) )
223
+ {
224
+ Mix_HaltChannel( sound->channel );
225
+ }
226
+
227
+ /* Find first available channel */
228
+ sound->channel = Mix_GroupAvailable(-1);
229
+
230
+ if( sound->channel == -1 )
231
+ {
232
+ /* No channels were available, so make one more than there are now.
233
+ * (Mix_AllocateChannels(-1) returns the current number of channels)
234
+ */
235
+ Mix_AllocateChannels( Mix_AllocateChannels(-1) + 1 );
236
+
237
+ /* Try again. */
238
+ sound->channel = Mix_GroupAvailable(-1);
239
+ }
240
+
241
+ /* Set its volume before we play */
242
+ Mix_Volume( sound->channel, (int)(MIX_MAX_VOLUME * sound->volume) );
243
+
244
+
245
+ if( fade_in <= 0 )
246
+ {
247
+ /* Play sound without fading in */
248
+ return Mix_PlayChannelTimed( sound->channel, sound->wrap->chunk,
249
+ repeats, stop_after );
250
+ }
251
+ else
252
+ {
253
+ /* Play sound with fading in */
254
+ return Mix_FadeInChannelTimed( sound->channel, sound->wrap->chunk,
255
+ repeats, fade_in, stop_after );
256
+ }
257
+ }
258
+
259
+
260
+ /* Ruby allocation function. */
261
+ static VALUE rg_sound_alloc( VALUE klass )
262
+ {
263
+ RG_Sound *sound = _rg_sound_alloc();
264
+ return Data_Wrap_Struct(klass, 0, _rg_sound_free, sound);
265
+ }
266
+
267
+
268
+
269
+ /*
270
+ * call-seq:
271
+ * load( filename ) -> sound
272
+ *
273
+ * Load the given audio file.
274
+ * Supported file formats are WAV, AIFF, RIFF, OGG (Ogg Vorbis), and
275
+ * VOC (SoundBlaster).
276
+ *
277
+ * filename:: Full or relative path to the file. (String, required)
278
+ *
279
+ * Returns:: The new Sound instance. (Sound)
280
+ * May raise:: SDLError, if the sound file could not be loaded.
281
+ *
282
+ */
283
+ static VALUE rg_sound_load( VALUE klass, VALUE filename )
284
+ {
285
+ RG_Sound *sound;
286
+
287
+ VALUE s = rg_sound_alloc( cSound );
288
+
289
+ Data_Get_Struct( s, RG_Sound, sound );
290
+
291
+ char *file = StringValuePtr( filename );
292
+
293
+ int result = _rg_sound_load( sound, file );
294
+
295
+ if( result == -1 )
296
+ {
297
+ rb_raise(eSDLError, "Could not load Sound file '%s': %s",
298
+ file, Mix_GetError());
299
+ }
300
+
301
+ return s;
302
+ }
303
+
304
+
305
+ /*
306
+ * call-seq:
307
+ * Sound.autoload( filename ) -> Surface or nil
308
+ *
309
+ * Searches each directory in Sound.autoload_dirs for a file with
310
+ * the given filename. If it finds that file, loads it and returns
311
+ * a Sound instance. If it doesn't find the file, returns nil.
312
+ *
313
+ * See Rubygame::NamedResource for more information about this
314
+ * functionality.
315
+ *
316
+ */
317
+ VALUE rg_sound_autoload( VALUE klass, VALUE namev )
318
+ {
319
+ VALUE pathv = rb_funcall( klass, rb_intern("find_file"), 1, namev );
320
+
321
+ if( RTEST(pathv) )
322
+ {
323
+ return rg_sound_load( klass, pathv );
324
+ }
325
+ else
326
+ {
327
+ return Qnil;
328
+ }
329
+ }
330
+
331
+
332
+ /*
333
+ *
334
+ * call-seq:
335
+ * new
336
+ *
337
+ * **NOTE**: Don't use this method. Use Sound.load.
338
+ *
339
+ * This method is not implemented. (In the future, it might be
340
+ * used to create a new Sound with blank audio data.)
341
+ *
342
+ * Raises NotImplementedError.
343
+ *
344
+ */
345
+ static VALUE rg_sound_new( int argc, VALUE *ARGV, VALUE self )
346
+ {
347
+ rb_raise(rb_eNotImpError, "Sound.new is not implemented yet. Use Sound.load to load a sound file.");
348
+ }
349
+
350
+
351
+ /*
352
+ * call-seq:
353
+ * clone( other ) -> sound
354
+ * dup( other ) -> sound
355
+ *
356
+ * Create a copy of the given Sound instance. Much more memory-efficient
357
+ * than using #load to load the sound file again.
358
+ *
359
+ * other:: An existing Sound instance. (Sound, required)
360
+ *
361
+ * Returns:: The new Sound instance. (Sound)
362
+ *
363
+ * **NOTE**: #clone and #dup do slightly different things; #clone will copy
364
+ * the 'frozen' state of the object, while #dup will create a fresh, un-frozen
365
+ * object.
366
+ *
367
+ */
368
+ static VALUE rg_sound_initialize_copy( VALUE self, VALUE other )
369
+ {
370
+ RG_Sound *soundA, *soundB;
371
+ Data_Get_Struct(self, RG_Sound, soundA);
372
+ Data_Get_Struct(other, RG_Sound, soundB);
373
+
374
+ _rg_sound_copy( soundA, soundB );
375
+
376
+ return self;
377
+ }
378
+
379
+
380
+
381
+
382
+ /*
383
+ * call-seq:
384
+ * play( options={} ) -> self
385
+ *
386
+ * Play the Sound, optionally fading in, repeating a certain number of
387
+ * times (or forever), and/or stopping automatically after a certain time.
388
+ *
389
+ * See also #pause and #stop.
390
+ *
391
+ * options:: Hash of options, listed below. (Hash, required)
392
+ *
393
+ * :fade_in:: Fade in from silence over the given number of seconds.
394
+ * (Numeric)
395
+ * :repeats:: Repeat the sound the given number of times, or forever
396
+ * (or until stopped) if -1. (Integer)
397
+ * :stop_after:: Automatically stop playing after playing for the given
398
+ * number of seconds. (Numeric)
399
+ *
400
+ * Returns:: The receiver (self).
401
+ * May raise:: SDLError, if the sound file could not be played.
402
+ *
403
+ * **NOTE**: If the sound is already playing (or paused), it will be stopped
404
+ * and played again from the beginning.
405
+ *
406
+ * Example:
407
+ * # Fade in over 2 seconds, play 4 times (1 + 3 repeats),
408
+ * # but stop playing after 5 seconds.
409
+ * sound.play( :fade_in => 2, :repeats => 3, :stop_after => 5 );
410
+ *
411
+ */
412
+ static VALUE rg_sound_play( int argc, VALUE *argv, VALUE self )
413
+ {
414
+ RG_Sound *sound;
415
+ Data_Get_Struct(self, RG_Sound, sound);
416
+
417
+ VALUE options;
418
+ rb_scan_args(argc, argv, "01", &options);
419
+
420
+ int fade_in = 0;
421
+ int repeats = 0;
422
+ int stop_after = -1;
423
+
424
+ /* If we got some options */
425
+ if( RTEST(options) )
426
+ {
427
+ /* Make sure options is a Hash table */
428
+ if( TYPE(options) != T_HASH )
429
+ {
430
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Hash)",
431
+ rb_obj_classname(options));
432
+ }
433
+
434
+ VALUE temp;
435
+
436
+ temp = rb_hash_aref(options, make_symbol("fade_in"));
437
+ if( RTEST(temp) )
438
+ {
439
+ fade_in = (int)(1000 * NUM2DBL( temp ));
440
+ }
441
+
442
+ temp = rb_hash_aref(options, make_symbol("repeats"));
443
+ if( RTEST(temp) )
444
+ {
445
+ repeats = NUM2INT(temp);
446
+ }
447
+
448
+ temp = rb_hash_aref(options, make_symbol("stop_after"));
449
+ if( RTEST(temp) )
450
+ {
451
+ stop_after = (int)(1000 * NUM2DBL( temp ));
452
+ }
453
+
454
+ }
455
+
456
+ int result = _rg_sound_play( sound, fade_in, repeats, stop_after );
457
+
458
+ if( result == -1 )
459
+ {
460
+ rb_raise(eSDLError, "Could not play Sound: %s", Mix_GetError());
461
+ }
462
+
463
+ return self;
464
+ }
465
+
466
+
467
+ /*
468
+ * call-seq:
469
+ * playing? -> true or false
470
+ *
471
+ * True if the Sound is currently playing (not paused or stopped).
472
+ * See also #paused? and #stopped?.
473
+ *
474
+ */
475
+ static VALUE rg_sound_playingp( VALUE self )
476
+ {
477
+ RG_Sound *sound;
478
+ Data_Get_Struct(self, RG_Sound, sound);
479
+
480
+ int channel = sound->channel;
481
+
482
+ /* Make sure the sound actually belongs to the channel */
483
+ if( _rg_sound_channel_check(sound) )
484
+ {
485
+ /* Return true if it's playing, but not paused. */
486
+ if( Mix_Playing(channel) && !Mix_Paused(channel) )
487
+ {
488
+ return Qtrue;
489
+ }
490
+ else
491
+ {
492
+ return Qfalse;
493
+ }
494
+ }
495
+ else
496
+ {
497
+ return Qfalse;
498
+ }
499
+ }
500
+
501
+
502
+
503
+ /*
504
+ * call-seq:
505
+ * pause -> self
506
+ *
507
+ * Pause the Sound. Unlike #stop, it can be unpaused later to resume
508
+ * from where it was paused. See also #unpause and #paused?.
509
+ *
510
+ * Returns:: The receiver (self).
511
+ *
512
+ * **NOTE**: Does nothing if the sound is not currently playing.
513
+ *
514
+ */
515
+ static VALUE rg_sound_pause( VALUE self )
516
+ {
517
+ RG_Sound *sound;
518
+ Data_Get_Struct(self, RG_Sound, sound);
519
+
520
+ int channel = sound->channel;
521
+
522
+ /* Make sure the sound actually belongs to the channel */
523
+ if( _rg_sound_channel_check(sound) )
524
+ {
525
+ Mix_Pause( channel );
526
+ }
527
+
528
+ return self;
529
+ }
530
+
531
+
532
+ /*
533
+ * call-seq:
534
+ * unpause -> self
535
+ *
536
+ * Unpause the Sound, if it is currently paused. Resumes from
537
+ * where it was paused. See also #pause and #paused?.
538
+ *
539
+ * Returns:: The receiver (self).
540
+ *
541
+ * **NOTE**: Does nothing if the sound is not currently paused.
542
+ *
543
+ */
544
+ static VALUE rg_sound_unpause( VALUE self )
545
+ {
546
+ RG_Sound *sound;
547
+ Data_Get_Struct(self, RG_Sound, sound);
548
+
549
+ int channel = sound->channel;
550
+
551
+ /* Make sure the sound actually belongs to the channel */
552
+ if( _rg_sound_channel_check(sound) )
553
+ {
554
+ Mix_Resume( channel );
555
+ }
556
+
557
+ return self;
558
+ }
559
+
560
+
561
+ /*
562
+ * call-seq:
563
+ * paused? -> true or false
564
+ *
565
+ * True if the Sound is currently paused (not playing or stopped).
566
+ * See also #playing? and #stopped?.
567
+ *
568
+ */
569
+ static VALUE rg_sound_pausedp( VALUE self )
570
+ {
571
+ RG_Sound *sound;
572
+ Data_Get_Struct(self, RG_Sound, sound);
573
+
574
+ int channel = sound->channel;
575
+
576
+ /* Make sure the sound actually belongs to the channel */
577
+ if( _rg_sound_channel_check(sound) )
578
+ {
579
+ /* Return true if it's "playing" (not stopped), as well as paused. */
580
+ if( Mix_Playing(channel) && Mix_Paused(channel) )
581
+ {
582
+ return Qtrue;
583
+ }
584
+ else
585
+ {
586
+ return Qfalse;
587
+ }
588
+ }
589
+ else
590
+ {
591
+ return Qfalse;
592
+ }
593
+ }
594
+
595
+
596
+
597
+ /*
598
+ * call-seq:
599
+ * stop -> self
600
+ *
601
+ * Stop the Sound. Unlike #pause, the sound must be played again from
602
+ * the beginning, it cannot be resumed from it was stopped.
603
+ *
604
+ * Returns:: The receiver (self).
605
+ *
606
+ * **NOTE**: Does nothing if the sound is not currently playing or paused.
607
+ *
608
+ */
609
+ static VALUE rg_sound_stop( VALUE self )
610
+ {
611
+ RG_Sound *sound;
612
+ Data_Get_Struct(self, RG_Sound, sound);
613
+
614
+ int channel = sound->channel;
615
+
616
+ /* Make sure the sound actually belongs to the channel */
617
+ if( _rg_sound_channel_check(sound) )
618
+ {
619
+ Mix_HaltChannel( channel );
620
+ }
621
+
622
+ return self;
623
+ }
624
+
625
+
626
+ /*
627
+ * call-seq:
628
+ * stopped? -> true or false
629
+ *
630
+ * True if the Sound is currently stopped (not playing or paused).
631
+ * See also #playing? and #paused?.
632
+ *
633
+ */
634
+ static VALUE rg_sound_stoppedp( VALUE self )
635
+ {
636
+ RG_Sound *sound;
637
+ Data_Get_Struct(self, RG_Sound, sound);
638
+
639
+ int channel = sound->channel;
640
+
641
+ /* Make sure the sound actually belongs to the channel */
642
+ if( _rg_sound_channel_check(sound) )
643
+ {
644
+ /* Return true if it's not playing. */
645
+ if( !Mix_Playing(channel) )
646
+ {
647
+ return Qtrue;
648
+ }
649
+ else
650
+ {
651
+ return Qfalse;
652
+ }
653
+ }
654
+ else
655
+ {
656
+ /* If it's not on a channel... it can't be playing! */
657
+ return Qtrue;
658
+ }
659
+ }
660
+
661
+
662
+ /*
663
+ * call-seq:
664
+ * fade_out( fade_time ) -> self
665
+ *
666
+ * Fade out to silence over the given number of seconds. Once the sound
667
+ * is silent, it is automatically stopped.
668
+ *
669
+ * Returns:: The receiver (self).
670
+ *
671
+ * **NOTE**: If the sound is currently paused, the fade will start,
672
+ * but you won't be able to hear it happening unless you #unpause during
673
+ * the fade. Does nothing if the sound is currently stopped.
674
+ *
675
+ */
676
+ static VALUE rg_sound_fadeout( VALUE self, VALUE fade_time )
677
+ {
678
+ RG_Sound *sound;
679
+ Data_Get_Struct(self, RG_Sound, sound);
680
+
681
+ int channel = sound->channel;
682
+ int fade_ms = (int)(1000 * NUM2DBL(fade_time));
683
+
684
+ /* Make sure the sound actually belongs to the channel */
685
+ if( _rg_sound_channel_check(sound) )
686
+ {
687
+ Mix_FadeOutChannel( channel, fade_ms );
688
+ }
689
+
690
+ return self;
691
+ }
692
+
693
+
694
+ /*
695
+ * call-seq:
696
+ * fading?( direction=:either ) -> true or false
697
+ *
698
+ * True if the Sound is currently fading in or out.
699
+ * See also #play and #fade_out.
700
+ *
701
+ * direction:: Check if it is fading :in, :out, or :either.
702
+ * (Symbol, required)
703
+ *
704
+ */
705
+ static VALUE rg_sound_fadingp( int argc, VALUE *argv, VALUE self )
706
+ {
707
+ RG_Sound *sound;
708
+ Data_Get_Struct(self, RG_Sound, sound);
709
+
710
+ VALUE vdirection;
711
+ rb_scan_args(argc, argv, "01", &vdirection);
712
+
713
+ int direction;
714
+ int channel = sound->channel;
715
+
716
+ /* If it's not actually on a channel, return false right away. */
717
+ if( !(_rg_sound_channel_check(sound)) )
718
+ {
719
+ return Qfalse;
720
+ }
721
+
722
+ if( RTEST(vdirection) )
723
+ {
724
+ if( make_symbol("in") == vdirection )
725
+ {
726
+ return ( (Mix_FadingChannel(channel) == MIX_FADING_IN) ? Qtrue : Qfalse );
727
+ }
728
+
729
+ else if( make_symbol("out") == vdirection )
730
+ {
731
+ return ( (Mix_FadingChannel(channel) == MIX_FADING_OUT) ? Qtrue : Qfalse );
732
+ }
733
+
734
+ else if( make_symbol("either") == vdirection )
735
+ {
736
+ return ( (Mix_FadingChannel(channel) != MIX_NO_FADING) ? Qtrue : Qfalse );
737
+ }
738
+ }
739
+
740
+ /* default */
741
+ return ( (Mix_FadingChannel(channel) != MIX_NO_FADING) ? Qtrue : Qfalse );
742
+ }
743
+
744
+
745
+
746
+ /*
747
+ * call-seq:
748
+ * volume -> vol
749
+ *
750
+ * Return the volume level of the sound.
751
+ * 0.0 is totally silent, 1.0 is full volume.
752
+ *
753
+ * **NOTE**: Ignores fading in or out.
754
+ *
755
+ */
756
+ static VALUE rg_sound_getvolume( VALUE self )
757
+ {
758
+ RG_Sound *sound;
759
+ Data_Get_Struct(self, RG_Sound, sound);
760
+
761
+ return rb_float_new(sound->volume);
762
+ }
763
+
764
+
765
+ /*
766
+ * call-seq:
767
+ * volume = new_vol
768
+ *
769
+ * Set the new #volume level of the sound.
770
+ * 0.0 is totally silent, 1.0 is full volume.
771
+ *
772
+ * Volume cannot be set while the sound is fading in or out.
773
+ * Be sure to check #fading? or rescue from SDLError when
774
+ * using this method.
775
+ *
776
+ * May raise:: SDLError if the sound is fading in or out.
777
+ *
778
+ */
779
+ static VALUE rg_sound_setvolume( VALUE self, VALUE volume )
780
+ {
781
+ RG_Sound *sound;
782
+ Data_Get_Struct(self, RG_Sound, sound);
783
+
784
+ /* Change channel volume if Sound is currently assigned to a channel */
785
+ if( _rg_sound_channel_check(sound) )
786
+ {
787
+ /* But only if it's not fading right now. */
788
+ if( Mix_FadingChannel(sound->channel) == MIX_NO_FADING )
789
+ {
790
+ sound->volume = NUM2DBL(volume);
791
+ Mix_Volume( sound->channel, (int)(MIX_MAX_VOLUME * sound->volume) );
792
+ }
793
+ else
794
+ {
795
+ rb_raise(eSDLError, "cannot set Sound volume while fading");
796
+ }
797
+ }
798
+ else
799
+ {
800
+ /* Save it for later. */
801
+ sound->volume = NUM2DBL(volume);
802
+ }
803
+
804
+ return volume;
805
+ }
806
+
807
+
808
+ void Rubygame_Init_Sound()
809
+ {
810
+ #if 0
811
+ mRubygame = rb_define_module("Rubygame");
812
+ #endif
813
+
814
+ /*
815
+ * **IMPORTANT**: Sound is only available if Rubygame was compiled
816
+ * with SDL_mixer support!
817
+ *
818
+ * Sound holds a sound effect, loaded from an audio file (see #load for
819
+ * supported formats).
820
+ *
821
+ * Sound can #play, #pause/#unpause, #stop, adjust #volume,
822
+ * and #fade_out (you can fade in by passing an option to #play).
823
+ *
824
+ * Sound can create duplicates (with #dup or #clone) in a memory-efficient
825
+ * way -- the new Sound instance refers back to the same audio data,
826
+ * so having 100 duplicates of a sound uses only slightly more memory
827
+ * than having the first sound. Duplicates can different volume levels,
828
+ * too!
829
+ *
830
+ * Sound includes the Rubygame::NamedResource mixin module, which
831
+ * can perform autoloading of sounds on demand, among other things.
832
+ *
833
+ */
834
+ cSound = rb_define_class_under(mRubygame,"Sound",rb_cObject);
835
+
836
+ /* Include the Rubygame::NamedResource mixin module. */
837
+ rg_include_named_resource(cSound);
838
+
839
+ rb_define_alloc_func( cSound, rg_sound_alloc );
840
+
841
+ rb_define_singleton_method( cSound, "new", rg_sound_new, -1 );
842
+ rb_define_singleton_method( cSound, "load", rg_sound_load, 1 );
843
+
844
+ rb_define_singleton_method( cSound, "autoload", rg_sound_autoload, 1 );
845
+
846
+ rb_define_method( cSound, "initialize_copy", rg_sound_initialize_copy, 1 );
847
+
848
+ rb_define_method( cSound, "play", rg_sound_play, -1 );
849
+ rb_define_method( cSound, "playing?", rg_sound_playingp, 0 );
850
+
851
+ rb_define_method( cSound, "pause", rg_sound_pause, 0 );
852
+ rb_define_method( cSound, "unpause", rg_sound_unpause, 0 );
853
+ rb_define_method( cSound, "paused?", rg_sound_pausedp, 0 );
854
+
855
+ rb_define_method( cSound, "stop", rg_sound_stop, 0 );
856
+ rb_define_method( cSound, "stopped?", rg_sound_stoppedp, 0 );
857
+
858
+ rb_define_method( cSound, "fade_out", rg_sound_fadeout, 1 );
859
+ rb_define_method( cSound, "fading?", rg_sound_fadingp, -1 );
860
+
861
+ rb_define_method( cSound, "volume", rg_sound_getvolume, 0 );
862
+ rb_define_method( cSound, "volume=", rg_sound_setvolume, 1 );
863
+ }