sfml3-rb 0.2.2 → 0.3.1

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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +67 -16
  4. data/README.md +123 -32
  5. data/TODO.md +18 -11
  6. data/ext/audio/audio_enums.c +58 -20
  7. data/ext/audio/listener.c +89 -6
  8. data/ext/audio/music.c +212 -5
  9. data/ext/audio/sound.c +218 -9
  10. data/ext/audio/sound_buffer.c +197 -47
  11. data/ext/audio/sound_buffer_recorder.c +90 -18
  12. data/ext/audio/sound_recorder.c +188 -58
  13. data/ext/audio/sound_source_cone.c +127 -33
  14. data/ext/audio/sound_stream.c +204 -21
  15. data/ext/core/exceptions.c +10 -8
  16. data/ext/core/unicode.c +12 -2
  17. data/ext/ext.c +8 -0
  18. data/ext/graphics/blend_mode.c +218 -60
  19. data/ext/graphics/circle.c +300 -16
  20. data/ext/graphics/color.c +253 -94
  21. data/ext/graphics/drawable.c +16 -4
  22. data/ext/graphics/font.c +144 -25
  23. data/ext/graphics/glyph.c +38 -8
  24. data/ext/graphics/image.c +205 -41
  25. data/ext/graphics/polygon.c +317 -30
  26. data/ext/graphics/rect.c +225 -60
  27. data/ext/graphics/rectangle.c +307 -35
  28. data/ext/graphics/render_state.c +124 -12
  29. data/ext/graphics/render_texture.c +191 -14
  30. data/ext/graphics/render_window.c +55 -0
  31. data/ext/graphics/render_window.h +10 -0
  32. data/ext/graphics/shader.c +289 -17
  33. data/ext/graphics/shape.c +265 -32
  34. data/ext/graphics/sprite.c +245 -30
  35. data/ext/graphics/stencil_mode.c +163 -46
  36. data/ext/graphics/target.c +121 -43
  37. data/ext/graphics/target.h +31 -17
  38. data/ext/graphics/text.c +339 -19
  39. data/ext/graphics/texture.c +291 -6
  40. data/ext/graphics/transform.c +178 -5
  41. data/ext/graphics/transformable.c +127 -12
  42. data/ext/graphics/vertex.c +98 -6
  43. data/ext/graphics/vertex_array.c +142 -21
  44. data/ext/graphics/vertex_buffer.c +154 -12
  45. data/ext/graphics/view.c +140 -6
  46. data/ext/network/ftp.c +278 -12
  47. data/ext/network/http.c +179 -44
  48. data/ext/network/ip_address.c +127 -35
  49. data/ext/network/network_enums.c +248 -141
  50. data/ext/network/packet.c +280 -41
  51. data/ext/network/socket_selector.c +98 -21
  52. data/ext/network/tcp_listener.c +82 -18
  53. data/ext/network/tcp_socket.c +135 -27
  54. data/ext/network/udp_socket.c +129 -28
  55. data/ext/ports.rb +7 -0
  56. data/ext/system/buffer.c +47 -16
  57. data/ext/system/clock.c +77 -12
  58. data/ext/system/input_stream.c +113 -51
  59. data/ext/system/sleep.c +10 -2
  60. data/ext/system/time.c +182 -40
  61. data/ext/system/vec2.c +166 -39
  62. data/ext/system/vec3.c +177 -39
  63. data/ext/window/clipboard.c +47 -17
  64. data/ext/window/context.c +66 -13
  65. data/ext/window/context_settings.c +132 -42
  66. data/ext/window/cursor.c +45 -9
  67. data/ext/window/event.c +164 -53
  68. data/ext/window/joystick.c +69 -3
  69. data/ext/window/keyboard.c +168 -116
  70. data/ext/window/mouse.c +64 -13
  71. data/ext/window/sensor.c +28 -2
  72. data/ext/window/touch.c +32 -12
  73. data/ext/window/video_mode.c +93 -31
  74. data/ext/window/vulkan.c +34 -6
  75. data/ext/window/window.c +228 -229
  76. data/ext/window/window.h +4 -4
  77. data/ext/window/window_base.c +251 -0
  78. data/ext/window/window_base.h +43 -0
  79. data/ext/window/window_base.inc +236 -0
  80. data/lib/sfml/version.rb +1 -1
  81. data/sig/audio/audio_enums.rbs +30 -0
  82. data/sig/audio/listener.rbs +16 -0
  83. data/sig/audio/music.rbs +56 -0
  84. data/sig/audio/sound.rbs +51 -0
  85. data/sig/audio/sound_buffer.rbs +17 -0
  86. data/sig/audio/sound_buffer_recorder.rbs +14 -0
  87. data/sig/audio/sound_recorder.rbs +17 -0
  88. data/sig/audio/sound_source_cone.rbs +14 -0
  89. data/sig/audio/sound_stream.rbs +51 -0
  90. data/sig/graphics/blend_mode.rbs +29 -0
  91. data/sig/graphics/circle.rbs +44 -0
  92. data/sig/graphics/color.rbs +39 -0
  93. data/sig/graphics/drawable.rbs +5 -0
  94. data/sig/graphics/font.rbs +20 -0
  95. data/sig/graphics/glyph.rbs +7 -0
  96. data/sig/graphics/image.rbs +22 -0
  97. data/sig/graphics/polygon.rbs +42 -0
  98. data/sig/graphics/rect.rbs +33 -0
  99. data/sig/graphics/rectangle.rbs +42 -0
  100. data/sig/graphics/render_state.rbs +21 -0
  101. data/sig/graphics/render_target.rbs +18 -0
  102. data/sig/graphics/render_texture.rbs +39 -0
  103. data/sig/graphics/render_window.rbs +7 -0
  104. data/sig/graphics/shader.rbs +39 -0
  105. data/sig/graphics/shape.rbs +38 -0
  106. data/sig/graphics/sprite.rbs +34 -0
  107. data/sig/graphics/stencil_mode.rbs +18 -0
  108. data/sig/graphics/target.rbs +8 -0
  109. data/sig/graphics/text.rbs +48 -0
  110. data/sig/graphics/texture.rbs +34 -0
  111. data/sig/graphics/transform.rbs +37 -0
  112. data/sig/graphics/transformable.rbs +25 -0
  113. data/sig/graphics/vertex.rbs +17 -0
  114. data/sig/graphics/vertex_array.rbs +17 -0
  115. data/sig/graphics/vertex_buffer.rbs +22 -0
  116. data/sig/graphics/view.rbs +23 -0
  117. data/sig/network/ftp.rbs +46 -0
  118. data/sig/network/http.rbs +27 -0
  119. data/sig/network/ip_address.rbs +22 -0
  120. data/sig/network/network_enums.rbs +95 -0
  121. data/sig/network/packet.rbs +40 -0
  122. data/sig/network/socket_selector.rbs +14 -0
  123. data/sig/network/tcp_listener.rbs +13 -0
  124. data/sig/network/tcp_socket.rbs +18 -0
  125. data/sig/network/udp_socket.rbs +17 -0
  126. data/sig/sfml/version.rbs +3 -0
  127. data/sig/system/buffer.rbs +11 -0
  128. data/sig/system/clock.rbs +13 -0
  129. data/sig/system/input_stream.rbs +7 -0
  130. data/sig/system/sleep.rbs +3 -0
  131. data/sig/system/time.rbs +28 -0
  132. data/sig/system/vec2.rbs +26 -0
  133. data/sig/system/vec3.rbs +27 -0
  134. data/sig/window/clipboard.rbs +8 -0
  135. data/sig/window/context.rbs +11 -0
  136. data/sig/window/context_settings.rbs +20 -0
  137. data/sig/window/cursor.rbs +6 -0
  138. data/sig/window/event.rbs +20 -0
  139. data/sig/window/joystick.rbs +15 -0
  140. data/sig/window/keyboard.rbs +10 -0
  141. data/sig/window/mouse.rbs +9 -0
  142. data/sig/window/sensor.rbs +8 -0
  143. data/sig/window/touch.rbs +6 -0
  144. data/sig/window/video_mode.rbs +16 -0
  145. data/sig/window/vulkan.rbs +7 -0
  146. data/sig/window/window.rbs +34 -0
  147. data/sig/window/window_base.rbs +33 -0
  148. metadata +76 -3
@@ -12,86 +12,182 @@ typedef struct {
12
12
 
13
13
  static VALUE rb_cSoundSourceCone;
14
14
 
15
- static void SoundSourceCone_free(void *ptr) {
15
+ static void SoundSourceCone_free(void* ptr) {
16
16
  free(ptr);
17
17
  }
18
18
 
19
19
  static const rb_data_type_t SoundSourceCone_data_type = {
20
20
  .wrap_struct_name = "SFML::SoundSourceCone",
21
21
  .function = {.dmark = NULL, .dfree = SoundSourceCone_free, .dsize = NULL},
22
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
23
- };
22
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
24
23
 
25
24
  static VALUE SoundSourceCone_wrap(sfSoundSourceCone cone) {
26
- SoundSourceCone *ptr = malloc(sizeof(SoundSourceCone));
25
+ SoundSourceCone* ptr = malloc(sizeof(SoundSourceCone));
27
26
 
28
27
  ptr->cone = cone;
29
28
 
30
29
  return TypedData_Wrap_Struct(rb_cSoundSourceCone, &SoundSourceCone_data_type, ptr);
31
30
  }
32
31
 
33
- static VALUE SoundSourceCone_new(VALUE klass, VALUE rb_inner, VALUE rb_outer, VALUE rb_gain) {
34
- sfSoundSourceCone cone = {
35
- .innerAngle = (float) NUM2DBL(rb_inner),
36
- .outerAngle = (float) NUM2DBL(rb_outer),
37
- .outerGain = (float) NUM2DBL(rb_gain)
38
- };
32
+ static VALUE SoundSourceCone_alloc(VALUE klass) {
33
+ SoundSourceCone* ptr = malloc(sizeof(SoundSourceCone));
39
34
 
40
- return SoundSourceCone_wrap(cone);
35
+ if (ptr == NULL) {
36
+ rb_raise(rb_eNoMemError, "failed to allocate sound source cone");
37
+ }
38
+
39
+ ptr->cone = (sfSoundSourceCone){0.0f, 0.0f, 0.0f};
40
+
41
+ return TypedData_Wrap_Struct(klass, &SoundSourceCone_data_type, ptr);
41
42
  }
42
43
 
44
+ /* call-seq:
45
+ * SoundSourceCone.new(inner_angle, outer_angle, outer_gain) -> SoundSourceCone
46
+ *
47
+ * Creates a directional attenuation cone with the given angles and gain.
48
+ *
49
+ * @return [SoundSourceCone]
50
+ */
51
+ static VALUE SoundSourceCone_initialize(VALUE self, VALUE rb_inner, VALUE rb_outer, VALUE rb_gain) {
52
+ sfSoundSourceCone cone = {.innerAngle = (float)NUM2DBL(rb_inner),
53
+ .outerAngle = (float)NUM2DBL(rb_outer),
54
+ .outerGain = (float)NUM2DBL(rb_gain)};
55
+
56
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone = cone;
57
+
58
+ return self;
59
+ }
60
+
61
+ /* call-seq: inner_angle -> Float
62
+ *
63
+ * Returns the inner cone angle in degrees.
64
+ *
65
+ * @return [Float] angle, in degrees, of the inner cone within which the
66
+ * source is heard at full volume
67
+ */
43
68
  static VALUE SoundSourceCone_get_inner_angle(VALUE self) {
44
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.innerAngle);
69
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.innerAngle);
45
70
  }
46
71
 
72
+ /* call-seq: outer_angle -> Float
73
+ *
74
+ * Returns the outer cone angle in degrees.
75
+ *
76
+ * @return [Float] angle, in degrees, of the outer cone beyond which the
77
+ * source is heard at +outer_gain+ volume
78
+ */
47
79
  static VALUE SoundSourceCone_get_outer_angle(VALUE self) {
48
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerAngle);
80
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerAngle);
49
81
  }
50
82
 
83
+ /* call-seq: outer_gain -> Float
84
+ *
85
+ * Returns the gain applied outside the outer cone.
86
+ *
87
+ * @return [Float] volume factor applied outside the outer cone
88
+ */
51
89
  static VALUE SoundSourceCone_get_outer_gain(VALUE self) {
52
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerGain);
90
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerGain);
53
91
  }
54
92
 
93
+ /* call-seq:
94
+ * inner_angle=(value) -> Float
95
+ *
96
+ * Sets the inner cone angle in degrees.
97
+ *
98
+ * @return [Float] +value+
99
+ */
55
100
  static VALUE SoundSourceCone_set_inner_angle(VALUE self, VALUE rb_value) {
56
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.innerAngle = (float) NUM2DBL(rb_value);
101
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.innerAngle =
102
+ (float)NUM2DBL(rb_value);
57
103
  return rb_value;
58
104
  }
59
105
 
106
+ /* call-seq:
107
+ * outer_angle=(value) -> Float
108
+ *
109
+ * Sets the outer cone angle in degrees.
110
+ *
111
+ * @return [Float] +value+
112
+ */
60
113
  static VALUE SoundSourceCone_set_outer_angle(VALUE self, VALUE rb_value) {
61
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerAngle = (float) NUM2DBL(rb_value);
114
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerAngle =
115
+ (float)NUM2DBL(rb_value);
62
116
  return rb_value;
63
117
  }
64
118
 
119
+ /* call-seq:
120
+ * outer_gain=(value) -> Float
121
+ *
122
+ * Sets the gain applied outside the outer cone.
123
+ *
124
+ * @return [Float] +value+
125
+ */
65
126
  static VALUE SoundSourceCone_set_outer_gain(VALUE self, VALUE rb_value) {
66
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerGain = (float) NUM2DBL(rb_value);
127
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerGain = (float)NUM2DBL(rb_value);
67
128
  return rb_value;
68
129
  }
69
130
 
131
+ /* call-seq: to_a -> [Float, Float, Float]
132
+ *
133
+ * Returns the cone's three components as an Array.
134
+ *
135
+ * @return [Array<Float>] +[inner_angle, outer_angle, outer_gain]+
136
+ */
70
137
  static VALUE SoundSourceCone_to_a(VALUE self) {
71
- sfSoundSourceCone cone = ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone;
138
+ sfSoundSourceCone cone = ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone;
72
139
 
73
140
  return rb_ary_new_from_args(3, DBL2NUM(cone.innerAngle), DBL2NUM(cone.outerAngle),
74
141
  DBL2NUM(cone.outerGain));
75
142
  }
76
143
 
144
+ /* call-seq:
145
+ * self == other -> true or false
146
+ *
147
+ * Returns +true+ if +other+ is a cone with the same angles and gain.
148
+ *
149
+ * @return [Boolean]
150
+ */
77
151
  static VALUE SoundSourceCone_eql(VALUE self, VALUE rb_other) {
78
- sfSoundSourceCone a = ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone;
152
+ sfSoundSourceCone a = ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone;
79
153
  sfSoundSourceCone b;
80
154
 
81
155
  if (!rb_obj_is_kind_of(rb_other, rb_cSoundSourceCone)) {
82
156
  return Qfalse;
83
157
  }
84
158
 
85
- b = ((SoundSourceCone *) Get_SoundSourceCone_Struct(rb_other))->cone;
159
+ b = ((SoundSourceCone*)Get_SoundSourceCone_Struct(rb_other))->cone;
86
160
 
87
161
  return BOOL2RB(a.innerAngle == b.innerAngle && a.outerAngle == b.outerAngle &&
88
162
  a.outerGain == b.outerGain);
89
163
  }
90
164
 
91
- void Init_SoundSourceCone(VALUE rb_module) {
92
- rb_cSoundSourceCone = rb_define_class_under(rb_module, "SoundSourceCone", rb_cObject);
93
-
94
- rb_define_singleton_method(rb_cSoundSourceCone, "new", SoundSourceCone_new, 3);
165
+ /* Document-class: SFML::SoundSourceCone
166
+ * A directional attenuation cone for a SoundSource (SoundSource#cone) or the
167
+ * Listener (Listener.cone): within +inner_angle+ degrees of the facing
168
+ * direction the source is heard at full volume; beyond +outer_angle+
169
+ * degrees it is heard at +outer_gain+ volume, with a smooth transition in
170
+ * between.
171
+ *
172
+ * @!attribute inner_angle
173
+ * Angle, in degrees, of the inner cone within which the source is heard at
174
+ * full volume.
175
+ * @return [Float] angle, in degrees, of the inner cone within which the
176
+ * source is heard at full volume
177
+ * @!attribute outer_angle
178
+ * Angle, in degrees, of the outer cone beyond which the source is heard at
179
+ * +outer_gain+ volume.
180
+ * @return [Float] angle, in degrees, of the outer cone beyond which the
181
+ * source is heard at +outer_gain+ volume
182
+ * @!attribute outer_gain
183
+ * Volume factor applied outside the outer cone.
184
+ * @return [Float] volume factor applied outside the outer cone
185
+ */
186
+ void Init_SoundSourceCone(VALUE rb_mSFML) {
187
+ rb_cSoundSourceCone = rb_define_class_under(rb_mSFML, "SoundSourceCone", rb_cObject);
188
+
189
+ rb_define_alloc_func(rb_cSoundSourceCone, SoundSourceCone_alloc);
190
+ rb_define_method(rb_cSoundSourceCone, "initialize", SoundSourceCone_initialize, 3);
95
191
 
96
192
  rb_define_method(rb_cSoundSourceCone, "inner_angle", SoundSourceCone_get_inner_angle, 0);
97
193
  rb_define_method(rb_cSoundSourceCone, "outer_angle", SoundSourceCone_get_outer_angle, 0);
@@ -107,30 +203,28 @@ VALUE Get_Klass_SoundSourceCone(void) {
107
203
  return rb_cSoundSourceCone;
108
204
  }
109
205
 
110
- void *Get_SoundSourceCone_Struct(VALUE self) {
111
- SoundSourceCone *ptr;
206
+ void* Get_SoundSourceCone_Struct(VALUE self) {
207
+ SoundSourceCone* ptr;
112
208
  TypedData_Get_Struct(self, SoundSourceCone, &SoundSourceCone_data_type, ptr);
113
209
  return ptr;
114
210
  }
115
211
 
116
212
  sfSoundSourceCone sound_source_cone_from_rb(VALUE rb_cone) {
117
213
  if (rb_obj_is_kind_of(rb_cone, rb_cSoundSourceCone)) {
118
- return ((SoundSourceCone *) Get_SoundSourceCone_Struct(rb_cone))->cone;
214
+ return ((SoundSourceCone*)Get_SoundSourceCone_Struct(rb_cone))->cone;
119
215
  }
120
216
 
121
217
  if (RB_TYPE_P(rb_cone, T_ARRAY) && RARRAY_LEN(rb_cone) == 3) {
122
- sfSoundSourceCone cone = {
123
- .innerAngle = (float) NUM2DBL(rb_ary_entry(rb_cone, 0)),
124
- .outerAngle = (float) NUM2DBL(rb_ary_entry(rb_cone, 1)),
125
- .outerGain = (float) NUM2DBL(rb_ary_entry(rb_cone, 2))
126
- };
218
+ sfSoundSourceCone cone = {.innerAngle = (float)NUM2DBL(rb_ary_entry(rb_cone, 0)),
219
+ .outerAngle = (float)NUM2DBL(rb_ary_entry(rb_cone, 1)),
220
+ .outerGain = (float)NUM2DBL(rb_ary_entry(rb_cone, 2))};
127
221
 
128
222
  return cone;
129
223
  }
130
224
 
131
225
  raise_invalid_argument_class(rb_cSoundSourceCone);
132
226
 
133
- return (sfSoundSourceCone) {0.0f, 0.0f, 0.0f};
227
+ return (sfSoundSourceCone){0.0f, 0.0f, 0.0f};
134
228
  }
135
229
 
136
230
  VALUE sound_source_cone_to_rb(sfSoundSourceCone cone) {
@@ -49,17 +49,25 @@ static void* SoundStream_destroy_without_gvl(void* handle) {
49
49
  static void SoundStream_free(void* ptr) {
50
50
  SoundStream* stream = ptr;
51
51
 
52
- effect_processor_release(stream->source.effect_slot);
52
+ /* Destroy (which blocks until CSFML guarantees no in-flight audio-thread
53
+ callback still references this source) before releasing the effect
54
+ slot, not after -- see the matching comment in sound.c's Sound_free. */
53
55
  rb_thread_call_without_gvl(SoundStream_destroy_without_gvl, stream->source.handle, RUBY_UBF_IO,
54
56
  NULL);
57
+ effect_processor_release(stream->source.effect_slot);
55
58
  free(stream->samples);
56
59
  free(stream);
57
60
  }
58
61
 
62
+ /* Deliberately no RUBY_TYPED_FREE_IMMEDIATELY: SoundStream_free releases the
63
+ GVL for sfSoundStream_destroy, and freeing during GC (which the flag
64
+ requests) would let another thread allocate while GC is mid-cycle, which
65
+ Ruby aborts on as "object allocation during garbage collection phase".
66
+ Deferred finalization runs the same free with the GVL held and no GC in
67
+ progress. */
59
68
  static const rb_data_type_t SoundStream_data_type = {
60
69
  .wrap_struct_name = "SFML::SoundStream",
61
- .function = {.dmark = SoundStream_mark, .dfree = SoundStream_free, .dsize = NULL},
62
- .flags = RUBY_TYPED_FREE_IMMEDIATELY};
70
+ .function = {.dmark = SoundStream_mark, .dfree = SoundStream_free, .dsize = NULL}};
63
71
 
64
72
  /* Expands the stream's sample buffer if needed, then copies either a packed
65
73
  String of int16 or an Array of Integers into it. Returns the sample count. */
@@ -185,14 +193,48 @@ static void SoundStream_on_seek(sfTime time, void* userData) {
185
193
  run_on_ruby_thread(SoundStream_seek_run, &ctx, SOUND_STREAM_CALLBACK_TIMEOUT_MS);
186
194
  }
187
195
 
188
- static VALUE SoundStream_new(int argc, VALUE* argv, VALUE klass) {
196
+ static VALUE SoundStream_alloc(VALUE klass) {
197
+ SoundStream* ptr = malloc(sizeof(SoundStream));
198
+ VALUE self;
199
+
200
+ if (ptr == NULL) {
201
+ rb_raise(rb_eNoMemError, "failed to allocate sound stream");
202
+ }
203
+
204
+ ptr->source.handle = NULL;
205
+ ptr->source.effect_slot = -1;
206
+ ptr->rb_self = Qnil;
207
+ ptr->samples = NULL;
208
+ ptr->samples_capacity = 0;
209
+
210
+ self = TypedData_Wrap_Struct(klass, &SoundStream_data_type, ptr);
211
+ ptr->rb_self = self;
212
+
213
+ return self;
214
+ }
215
+
216
+ /* call-seq:
217
+ * SoundStream.new(channel_count, sample_rate) -> SoundStream
218
+ * SoundStream.new(channel_count, sample_rate, channel_map) -> SoundStream
219
+ *
220
+ * SoundStream must be subclassed: the subclass is required to implement
221
+ * +#on_get_data+, called from a foreign audio thread whenever more samples
222
+ * are needed, and may optionally implement +#on_seek+. +channel_map+, if
223
+ * given, is an Array of channel Symbols (see SoundChannel), one per channel.
224
+ *
225
+ * @return [SoundStream]
226
+ * @raise [NotImplementedError] if the subclass does not define #on_get_data
227
+ * @raise [RuntimeError] if the underlying stream could not be created
228
+ */
229
+ static VALUE SoundStream_initialize(int argc, VALUE* argv, VALUE self) {
189
230
  VALUE rb_channel_count, rb_sample_rate, rb_channel_map;
190
231
  sfSoundChannel* channel_map = NULL;
191
232
  size_t channel_map_size = 0;
192
233
  SoundStream* ptr;
193
- VALUE self;
194
234
  long i;
195
235
 
236
+ TypedData_Get_Struct(self, SoundStream, &SoundStream_data_type, ptr);
237
+
196
238
  rb_scan_args(argc, argv, "21", &rb_channel_count, &rb_sample_rate, &rb_channel_map);
197
239
 
198
240
  if (!NIL_P(rb_channel_map)) {
@@ -208,19 +250,7 @@ static VALUE SoundStream_new(int argc, VALUE* argv, VALUE klass) {
208
250
  }
209
251
  }
210
252
 
211
- ptr = malloc(sizeof(SoundStream));
212
- ptr->source.handle = NULL;
213
- ptr->source.effect_slot = -1;
214
- ptr->rb_self = Qnil;
215
- ptr->samples = NULL;
216
- ptr->samples_capacity = 0;
217
-
218
- self = TypedData_Wrap_Struct(klass, &SoundStream_data_type, ptr);
219
- ptr->rb_self = self;
220
-
221
253
  if (!rb_respond_to(self, rb_intern("on_get_data"))) {
222
- /* The wrapper is already owned by Ruby; its dfree tolerates a NULL
223
- handle, so raising here just leaves it to be collected. */
224
254
  free(channel_map);
225
255
  rb_raise(rb_eNotImpError, "subclass must define #on_get_data");
226
256
  }
@@ -238,14 +268,33 @@ static VALUE SoundStream_new(int argc, VALUE* argv, VALUE klass) {
238
268
  return self;
239
269
  }
240
270
 
271
+ /* call-seq: channel_count -> Integer
272
+ *
273
+ * Returns the number of audio channels the stream produces.
274
+ *
275
+ * @return [Integer]
276
+ */
241
277
  static VALUE SoundStream_channel_count(VALUE self) {
242
278
  return UINT2NUM(sfSoundStream_getChannelCount(Get_SoundStream_Struct(self)));
243
279
  }
244
280
 
281
+ /* call-seq: sample_rate -> Integer
282
+ *
283
+ * Returns the stream's sample rate in samples per second.
284
+ *
285
+ * @return [Integer]
286
+ */
245
287
  static VALUE SoundStream_sample_rate(VALUE self) {
246
288
  return UINT2NUM(sfSoundStream_getSampleRate(Get_SoundStream_Struct(self)));
247
289
  }
248
290
 
291
+ /* call-seq: channel_map -> Array<Symbol>
292
+ *
293
+ * Returns the channel layout of the stream.
294
+ *
295
+ * @return [Array<Symbol>] one entry per channel, e.g.
296
+ * +[:front_left, :front_right]+
297
+ */
249
298
  static VALUE SoundStream_channel_map(VALUE self) {
250
299
  size_t count = 0;
251
300
  sfSoundChannel* map = sfSoundStream_getChannelMap(Get_SoundStream_Struct(self), &count);
@@ -271,10 +320,144 @@ static VALUE SoundStream_channel_map(VALUE self) {
271
320
  #undef SS_FN
272
321
  #undef SS_METHOD
273
322
 
274
- void Init_SoundStream(VALUE rb_module) {
275
- rb_cSoundStream = rb_define_class_under(rb_module, "SoundStream", rb_cObject);
276
-
277
- rb_define_singleton_method(rb_cSoundStream, "new", SoundStream_new, -1);
323
+ /* Document-class: SFML::SoundStream
324
+ * Base class for a custom audio source that generates or decodes its own
325
+ * samples on demand. Subclasses must implement +#on_get_data+, returning an
326
+ * Array of Integer samples or a packed String of int16 samples for the next
327
+ * chunk (or +nil+/+false+ to signal end of stream), and may implement
328
+ * +#on_seek(time)+ to support seeking.
329
+ *
330
+ * @!method play
331
+ * Starts playback, or resumes it when paused.
332
+ * @return [self]
333
+ * @!method pause
334
+ * Pauses playback, keeping the current playing offset.
335
+ * @return [self]
336
+ * @!method stop
337
+ * Stops playback and rewinds to the beginning. May briefly block the
338
+ * calling thread if an audio-thread callback for this source is in
339
+ * flight.
340
+ * @return [self]
341
+ * @!method status
342
+ * Returns the current playback status.
343
+ * @return [Symbol] one of +:stopped+, +:paused+, +:playing+
344
+ * @!method looping?
345
+ * Returns +true+ if playback loops back to the start on completion.
346
+ * @return [Boolean]
347
+ * @!method looping=(value)
348
+ * Enables or disables looping.
349
+ * @return [Boolean]
350
+ * @!method pitch
351
+ * Returns the pitch scaling factor.
352
+ * @return [Float]
353
+ * @!method pitch=(value)
354
+ * Sets the pitch scaling factor.
355
+ * @return [Float]
356
+ * @!method pan
357
+ * Returns the source's stereo pan.
358
+ * @return [Float] stereo pan, -1 (left) to 1 (right)
359
+ * @!method pan=(value)
360
+ * Sets the source's stereo pan.
361
+ * @return [Float]
362
+ * @!method volume
363
+ * Returns the source's volume.
364
+ * @return [Float] 0 to 100
365
+ * @!method volume=(value)
366
+ * Sets the source's volume.
367
+ * @return [Float]
368
+ * @!method spatialization_enabled?
369
+ * Returns +true+ if 3D spatialization is enabled.
370
+ * @return [Boolean]
371
+ * @!method spatialization_enabled=(value)
372
+ * Enables or disables 3D spatialization.
373
+ * @return [Boolean]
374
+ * @!method position
375
+ * Returns the source's position in 3D space.
376
+ * @return [Vector3]
377
+ * @!method position=(value)
378
+ * Sets the source's position in 3D space.
379
+ * @return [Vector3]
380
+ * @!method direction
381
+ * Returns the direction the source is facing.
382
+ * @return [Vector3]
383
+ * @!method direction=(value)
384
+ * Sets the direction the source is facing.
385
+ * @return [Vector3]
386
+ * @!method velocity
387
+ * Returns the source's velocity, used for Doppler calculations.
388
+ * @return [Vector3]
389
+ * @!method velocity=(value)
390
+ * Sets the source's velocity for Doppler calculations.
391
+ * @return [Vector3]
392
+ * @!method cone
393
+ * Returns the source's directional attenuation cone.
394
+ * @return [SoundSourceCone]
395
+ * @!method cone=(value)
396
+ * Sets the source's directional attenuation cone.
397
+ * @return [SoundSourceCone]
398
+ * @!method doppler_factor
399
+ * Returns the factor by which the Doppler effect is scaled.
400
+ * @return [Float]
401
+ * @!method doppler_factor=(value)
402
+ * Sets the factor by which the Doppler effect is scaled.
403
+ * @return [Float]
404
+ * @!method directional_attenuation_factor
405
+ * Returns the factor controlling directional attenuation.
406
+ * @return [Float]
407
+ * @!method directional_attenuation_factor=(value)
408
+ * Sets the factor controlling directional attenuation.
409
+ * @return [Float]
410
+ * @!method relative_to_listener?
411
+ * Returns +true+ if the source is positioned relative to the listener.
412
+ * @return [Boolean]
413
+ * @!method relative_to_listener=(value)
414
+ * Makes the source relative to, or independent of, the listener.
415
+ * @return [Boolean]
416
+ * @!method min_distance
417
+ * Returns the minimum distance of the distance-attenuation model.
418
+ * @return [Float]
419
+ * @!method min_distance=(value)
420
+ * Sets the minimum distance of the distance-attenuation model.
421
+ * @return [Float]
422
+ * @!method max_distance
423
+ * Returns the maximum distance of the distance-attenuation model.
424
+ * @return [Float]
425
+ * @!method max_distance=(value)
426
+ * Sets the maximum distance of the distance-attenuation model.
427
+ * @return [Float]
428
+ * @!method min_gain
429
+ * Returns the minimum gain of the distance-attenuation model.
430
+ * @return [Float]
431
+ * @!method min_gain=(value)
432
+ * Sets the minimum gain of the distance-attenuation model.
433
+ * @return [Float]
434
+ * @!method max_gain
435
+ * Returns the maximum gain of the distance-attenuation model.
436
+ * @return [Float]
437
+ * @!method max_gain=(value)
438
+ * Sets the maximum gain of the distance-attenuation model.
439
+ * @return [Float]
440
+ * @!method attenuation
441
+ * Returns the distance-attenuation factor.
442
+ * @return [Float]
443
+ * @!method attenuation=(value)
444
+ * Sets the distance-attenuation factor.
445
+ * @return [Float]
446
+ * @!method playing_offset
447
+ * Returns the current playing offset.
448
+ * @return [Time]
449
+ * @!method playing_offset=(value)
450
+ * Seeks to the given playing offset.
451
+ * @return [Time]
452
+ * @!method effect_processor=(proc)
453
+ * Installs a Proc that post-processes this source's audio in real time.
454
+ * @return [Proc] +proc+
455
+ */
456
+ void Init_SoundStream(VALUE rb_mSFML) {
457
+ rb_cSoundStream = rb_define_class_under(rb_mSFML, "SoundStream", rb_cObject);
458
+
459
+ rb_define_alloc_func(rb_cSoundStream, SoundStream_alloc);
460
+ rb_define_method(rb_cSoundStream, "initialize", SoundStream_initialize, -1);
278
461
 
279
462
  rb_define_method(rb_cSoundStream, "channel_count", SoundStream_channel_count, 0);
280
463
  rb_define_method(rb_cSoundStream, "sample_rate", SoundStream_sample_rate, 0);
@@ -2,9 +2,9 @@
2
2
 
3
3
  #include <string.h>
4
4
 
5
- #define MSG_LENGTH 86
5
+ #define MSG_LENGTH 86
6
6
 
7
- void raise_invalid_argument_type(const char *type) {
7
+ void raise_invalid_argument_type(const char* type) {
8
8
  char msg[MSG_LENGTH];
9
9
 
10
10
  snprintf(msg, MSG_LENGTH, "invalid argument, expected a %s object", type);
@@ -13,31 +13,33 @@ void raise_invalid_argument_type(const char *type) {
13
13
  }
14
14
 
15
15
  void raise_invalid_argument_class(VALUE rb_cKlass) {
16
- raise_invalid_argument_type(RSTRING_PTR(rb_funcall(rb_cKlass, rb_intern("name"), 0)));
16
+ VALUE rb_name = rb_funcall(rb_cKlass, rb_intern("name"), 0);
17
+
18
+ raise_invalid_argument_type(NIL_P(rb_name) ? "anonymous class" : RSTRING_PTR(rb_name));
17
19
  }
18
20
 
19
21
  void raise_invalid_arguments_excepted(int expected, size_t given) {
20
22
  char msg[MSG_LENGTH];
21
23
 
22
24
  if (expected > 0) {
23
- snprintf(msg, MSG_LENGTH, "wrong number of arguments (given %lu, expected %i)", given, expected);
25
+ snprintf(msg, MSG_LENGTH, "wrong number of arguments (given %zu, expected %i)", given,
26
+ expected);
24
27
  } else {
25
- snprintf(msg, MSG_LENGTH, "wrong number of arguments (given %lu)", given);
28
+ snprintf(msg, MSG_LENGTH, "wrong number of arguments (given %zu)", given);
26
29
  }
27
30
 
28
-
29
31
  rb_raise(rb_eArgError, "%s", msg);
30
32
  }
31
33
 
32
34
  void raise_invalid_array_length(size_t length) {
33
35
  char msg[MSG_LENGTH];
34
36
 
35
- snprintf(msg, MSG_LENGTH, "invalid array length, expected length of %lu", length);
37
+ snprintf(msg, MSG_LENGTH, "invalid array length, expected length of %zu", length);
36
38
 
37
39
  rb_raise(rb_eArgError, "%s", msg);
38
40
  }
39
41
 
40
- void raise_method_no_implemented(const char *method) {
42
+ void raise_method_no_implemented(const char* method) {
41
43
  if (method != NULL && strlen(method) > 0) {
42
44
  rb_raise(rb_eNotImpError, "method not implemented: %s", method);
43
45
  } else {
data/ext/core/unicode.c CHANGED
@@ -1,5 +1,6 @@
1
1
  #include "core/unicode.h"
2
2
 
3
+ #include <limits.h>
3
4
  #include <ruby.h>
4
5
  #include <ruby/encoding.h>
5
6
 
@@ -8,12 +9,21 @@ VALUE utf32_from_rb(VALUE rb_string) {
8
9
  VALUE string = rb_str_export_to_enc(rb_string, utf8);
9
10
  const char* cursor = RSTRING_PTR(string);
10
11
  const char* end = cursor + RSTRING_LEN(string);
12
+ long source_length = RSTRING_LEN(string);
11
13
  VALUE buffer;
12
14
  sfChar32* out;
13
15
  long length = 0;
14
16
 
15
- /* One code point per byte is the worst case, plus the terminator. */
16
- buffer = rb_str_tmp_new((RSTRING_LEN(string) + 1) * (long)sizeof(sfChar32));
17
+ /* One code point per byte is the worst case, plus the terminator. On a
18
+ 32-bit long (the 32-bit targets this gem ships), a large enough string
19
+ would overflow (source_length + 1) * sizeof(sfChar32) and allocate a
20
+ buffer far too small for the write loop below -- check the bound
21
+ before multiplying rather than after. */
22
+ if (source_length > (LONG_MAX / (long)sizeof(sfChar32)) - 1) {
23
+ rb_raise(rb_eArgError, "string too long to convert to UTF-32");
24
+ }
25
+
26
+ buffer = rb_str_tmp_new((source_length + 1) * (long)sizeof(sfChar32));
17
27
  out = (sfChar32*)RSTRING_PTR(buffer);
18
28
 
19
29
  while (cursor < end) {
data/ext/ext.c CHANGED
@@ -22,6 +22,7 @@
22
22
  #include "graphics/target.h"
23
23
  #include "graphics/render_state.h"
24
24
  #include "window/event.h"
25
+ #include "window/window_base.h"
25
26
  #include "window/window.h"
26
27
  #include "window/keyboard.h"
27
28
  #include "window/mouse.h"
@@ -47,6 +48,7 @@
47
48
  #include "graphics/font.h"
48
49
  #include "graphics/text.h"
49
50
  #include "graphics/render_texture.h"
51
+ #include "graphics/render_window.h"
50
52
  #include "graphics/shader.h"
51
53
  #include "audio/effect_processor.h"
52
54
  #include "audio/audio_enums.h"
@@ -84,6 +86,10 @@
84
86
 
85
87
  static VALUE rb_mExt;
86
88
 
89
+ /* Document-module: SFML
90
+ * Ruby bindings for SFML 3, via its C API, CSFML. Every class and module in
91
+ * this library lives under this namespace.
92
+ */
87
93
  void Init_sfml_ext(void) {
88
94
  rb_mExt = rb_define_module("SFML");
89
95
 
@@ -123,7 +129,9 @@ void Init_sfml_ext(void) {
123
129
  Init_Event(rb_mExt);
124
130
  Init_VideoMode(rb_mExt);
125
131
  Init_View(rb_mExt);
132
+ Init_WindowBase(rb_mExt);
126
133
  Init_Window(rb_mExt);
134
+ Init_RenderWindow(rb_mExt);
127
135
  Init_Keyboard(rb_mExt);
128
136
  Init_Mouse(rb_mExt);
129
137
  Init_Joystick(rb_mExt);