rubygame 2.3.0-x86-mswin32-60

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 (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
+ }