sfml3-rb 0.2.2 → 0.3.0

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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +43 -17
  4. data/README.md +97 -29
  5. data/ext/audio/audio_enums.c +58 -20
  6. data/ext/audio/listener.c +89 -6
  7. data/ext/audio/music.c +206 -5
  8. data/ext/audio/sound.c +175 -5
  9. data/ext/audio/sound_buffer.c +189 -47
  10. data/ext/audio/sound_buffer_recorder.c +83 -16
  11. data/ext/audio/sound_recorder.c +172 -52
  12. data/ext/audio/sound_source_cone.c +108 -29
  13. data/ext/audio/sound_stream.c +178 -5
  14. data/ext/core/exceptions.c +10 -8
  15. data/ext/core/unicode.c +12 -2
  16. data/ext/ext.c +4 -0
  17. data/ext/graphics/blend_mode.c +203 -53
  18. data/ext/graphics/circle.c +271 -4
  19. data/ext/graphics/color.c +240 -90
  20. data/ext/graphics/drawable.c +15 -4
  21. data/ext/graphics/font.c +138 -25
  22. data/ext/graphics/glyph.c +31 -8
  23. data/ext/graphics/image.c +180 -37
  24. data/ext/graphics/polygon.c +293 -26
  25. data/ext/graphics/rect.c +211 -54
  26. data/ext/graphics/rectangle.c +279 -26
  27. data/ext/graphics/render_state.c +116 -2
  28. data/ext/graphics/render_texture.c +163 -2
  29. data/ext/graphics/shader.c +283 -17
  30. data/ext/graphics/shape.c +252 -26
  31. data/ext/graphics/sprite.c +216 -25
  32. data/ext/graphics/stencil_mode.c +148 -39
  33. data/ext/graphics/target.c +67 -22
  34. data/ext/graphics/target.h +15 -15
  35. data/ext/graphics/text.c +306 -6
  36. data/ext/graphics/texture.c +257 -3
  37. data/ext/graphics/transform.c +178 -5
  38. data/ext/graphics/transformable.c +126 -2
  39. data/ext/graphics/vertex.c +79 -2
  40. data/ext/graphics/vertex_array.c +128 -16
  41. data/ext/graphics/vertex_buffer.c +124 -2
  42. data/ext/graphics/view.c +130 -2
  43. data/ext/network/ftp.c +249 -10
  44. data/ext/network/http.c +156 -38
  45. data/ext/network/ip_address.c +107 -26
  46. data/ext/network/network_enums.c +248 -141
  47. data/ext/network/packet.c +273 -39
  48. data/ext/network/socket_selector.c +91 -19
  49. data/ext/network/tcp_listener.c +75 -16
  50. data/ext/network/tcp_socket.c +128 -25
  51. data/ext/network/udp_socket.c +122 -26
  52. data/ext/ports.rb +7 -0
  53. data/ext/system/buffer.c +41 -12
  54. data/ext/system/clock.c +68 -9
  55. data/ext/system/input_stream.c +94 -42
  56. data/ext/system/sleep.c +10 -2
  57. data/ext/system/time.c +172 -34
  58. data/ext/system/vec2.c +156 -35
  59. data/ext/system/vec3.c +166 -35
  60. data/ext/window/clipboard.c +47 -17
  61. data/ext/window/context.c +59 -9
  62. data/ext/window/context_settings.c +116 -38
  63. data/ext/window/cursor.c +39 -9
  64. data/ext/window/event.c +163 -42
  65. data/ext/window/joystick.c +69 -3
  66. data/ext/window/keyboard.c +168 -116
  67. data/ext/window/mouse.c +36 -2
  68. data/ext/window/sensor.c +28 -2
  69. data/ext/window/touch.c +20 -2
  70. data/ext/window/video_mode.c +90 -19
  71. data/ext/window/vulkan.c +34 -6
  72. data/ext/window/window.c +340 -16
  73. data/lib/sfml/version.rb +1 -1
  74. data/sig/audio/audio_enums.rbs +30 -0
  75. data/sig/audio/listener.rbs +16 -0
  76. data/sig/audio/music.rbs +56 -0
  77. data/sig/audio/sound.rbs +51 -0
  78. data/sig/audio/sound_buffer.rbs +17 -0
  79. data/sig/audio/sound_buffer_recorder.rbs +14 -0
  80. data/sig/audio/sound_recorder.rbs +17 -0
  81. data/sig/audio/sound_source_cone.rbs +14 -0
  82. data/sig/audio/sound_stream.rbs +51 -0
  83. data/sig/graphics/blend_mode.rbs +29 -0
  84. data/sig/graphics/circle.rbs +44 -0
  85. data/sig/graphics/color.rbs +39 -0
  86. data/sig/graphics/drawable.rbs +5 -0
  87. data/sig/graphics/font.rbs +20 -0
  88. data/sig/graphics/glyph.rbs +7 -0
  89. data/sig/graphics/image.rbs +22 -0
  90. data/sig/graphics/polygon.rbs +42 -0
  91. data/sig/graphics/rect.rbs +33 -0
  92. data/sig/graphics/rectangle.rbs +42 -0
  93. data/sig/graphics/render_state.rbs +21 -0
  94. data/sig/graphics/render_texture.rbs +37 -0
  95. data/sig/graphics/shader.rbs +39 -0
  96. data/sig/graphics/shape.rbs +38 -0
  97. data/sig/graphics/sprite.rbs +34 -0
  98. data/sig/graphics/stencil_mode.rbs +18 -0
  99. data/sig/graphics/target.rbs +10 -0
  100. data/sig/graphics/text.rbs +48 -0
  101. data/sig/graphics/texture.rbs +34 -0
  102. data/sig/graphics/transform.rbs +37 -0
  103. data/sig/graphics/transformable.rbs +25 -0
  104. data/sig/graphics/vertex.rbs +17 -0
  105. data/sig/graphics/vertex_array.rbs +17 -0
  106. data/sig/graphics/vertex_buffer.rbs +22 -0
  107. data/sig/graphics/view.rbs +24 -0
  108. data/sig/network/ftp.rbs +46 -0
  109. data/sig/network/http.rbs +27 -0
  110. data/sig/network/ip_address.rbs +22 -0
  111. data/sig/network/network_enums.rbs +95 -0
  112. data/sig/network/packet.rbs +40 -0
  113. data/sig/network/socket_selector.rbs +14 -0
  114. data/sig/network/tcp_listener.rbs +13 -0
  115. data/sig/network/tcp_socket.rbs +18 -0
  116. data/sig/network/udp_socket.rbs +17 -0
  117. data/sig/system/buffer.rbs +11 -0
  118. data/sig/system/clock.rbs +13 -0
  119. data/sig/system/input_stream.rbs +7 -0
  120. data/sig/system/sleep.rbs +3 -0
  121. data/sig/system/time.rbs +28 -0
  122. data/sig/system/vec2.rbs +26 -0
  123. data/sig/system/vec3.rbs +27 -0
  124. data/sig/window/clipboard.rbs +8 -0
  125. data/sig/window/context.rbs +11 -0
  126. data/sig/window/context_settings.rbs +20 -0
  127. data/sig/window/cursor.rbs +6 -0
  128. data/sig/window/event.rbs +20 -0
  129. data/sig/window/joystick.rbs +15 -0
  130. data/sig/window/keyboard.rbs +10 -0
  131. data/sig/window/mouse.rbs +9 -0
  132. data/sig/window/sensor.rbs +8 -0
  133. data/sig/window/touch.rbs +6 -0
  134. data/sig/window/video_mode.rbs +16 -0
  135. data/sig/window/vulkan.rbs +7 -0
  136. data/sig/window/window.rbs +57 -0
  137. metadata +66 -2
@@ -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,6 +193,19 @@ 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
 
196
+ /* call-seq:
197
+ * SoundStream.new(channel_count, sample_rate) -> SoundStream
198
+ * SoundStream.new(channel_count, sample_rate, channel_map) -> SoundStream
199
+ *
200
+ * SoundStream must be subclassed: the subclass is required to implement
201
+ * +#on_get_data+, called from a foreign audio thread whenever more samples
202
+ * are needed, and may optionally implement +#on_seek+. +channel_map+, if
203
+ * given, is an Array of channel Symbols (see SoundChannel), one per channel.
204
+ *
205
+ * @return [SoundStream]
206
+ * @raise [NotImplementedError] if the subclass does not define #on_get_data
207
+ * @raise [RuntimeError] if the underlying stream could not be created
208
+ */
188
209
  static VALUE SoundStream_new(int argc, VALUE* argv, VALUE klass) {
189
210
  VALUE rb_channel_count, rb_sample_rate, rb_channel_map;
190
211
  sfSoundChannel* channel_map = NULL;
@@ -238,14 +259,33 @@ static VALUE SoundStream_new(int argc, VALUE* argv, VALUE klass) {
238
259
  return self;
239
260
  }
240
261
 
262
+ /* call-seq: channel_count -> Integer
263
+ *
264
+ * Returns the number of audio channels the stream produces.
265
+ *
266
+ * @return [Integer]
267
+ */
241
268
  static VALUE SoundStream_channel_count(VALUE self) {
242
269
  return UINT2NUM(sfSoundStream_getChannelCount(Get_SoundStream_Struct(self)));
243
270
  }
244
271
 
272
+ /* call-seq: sample_rate -> Integer
273
+ *
274
+ * Returns the stream's sample rate in samples per second.
275
+ *
276
+ * @return [Integer]
277
+ */
245
278
  static VALUE SoundStream_sample_rate(VALUE self) {
246
279
  return UINT2NUM(sfSoundStream_getSampleRate(Get_SoundStream_Struct(self)));
247
280
  }
248
281
 
282
+ /* call-seq: channel_map -> Array<Symbol>
283
+ *
284
+ * Returns the channel layout of the stream.
285
+ *
286
+ * @return [Array<Symbol>] one entry per channel, e.g.
287
+ * +[:front_left, :front_right]+
288
+ */
249
289
  static VALUE SoundStream_channel_map(VALUE self) {
250
290
  size_t count = 0;
251
291
  sfSoundChannel* map = sfSoundStream_getChannelMap(Get_SoundStream_Struct(self), &count);
@@ -271,8 +311,141 @@ static VALUE SoundStream_channel_map(VALUE self) {
271
311
  #undef SS_FN
272
312
  #undef SS_METHOD
273
313
 
274
- void Init_SoundStream(VALUE rb_module) {
275
- rb_cSoundStream = rb_define_class_under(rb_module, "SoundStream", rb_cObject);
314
+ /* Document-class: SFML::SoundStream
315
+ * Base class for a custom audio source that generates or decodes its own
316
+ * samples on demand. Subclasses must implement +#on_get_data+, returning an
317
+ * Array of Integer samples or a packed String of int16 samples for the next
318
+ * chunk (or +nil+/+false+ to signal end of stream), and may implement
319
+ * +#on_seek(time)+ to support seeking.
320
+ *
321
+ * @!method play
322
+ * Starts playback, or resumes it when paused.
323
+ * @return [self]
324
+ * @!method pause
325
+ * Pauses playback, keeping the current playing offset.
326
+ * @return [self]
327
+ * @!method stop
328
+ * Stops playback and rewinds to the beginning. May briefly block the
329
+ * calling thread if an audio-thread callback for this source is in
330
+ * flight.
331
+ * @return [self]
332
+ * @!method status
333
+ * Returns the current playback status.
334
+ * @return [Symbol] one of +:stopped+, +:paused+, +:playing+
335
+ * @!method looping?
336
+ * Returns +true+ if playback loops back to the start on completion.
337
+ * @return [Boolean]
338
+ * @!method looping=(value)
339
+ * Enables or disables looping.
340
+ * @return [Boolean]
341
+ * @!method pitch
342
+ * Returns the pitch scaling factor.
343
+ * @return [Float]
344
+ * @!method pitch=(value)
345
+ * Sets the pitch scaling factor.
346
+ * @return [Float]
347
+ * @!method pan
348
+ * Returns the source's stereo pan.
349
+ * @return [Float] stereo pan, -1 (left) to 1 (right)
350
+ * @!method pan=(value)
351
+ * Sets the source's stereo pan.
352
+ * @return [Float]
353
+ * @!method volume
354
+ * Returns the source's volume.
355
+ * @return [Float] 0 to 100
356
+ * @!method volume=(value)
357
+ * Sets the source's volume.
358
+ * @return [Float]
359
+ * @!method spatialization_enabled?
360
+ * Returns +true+ if 3D spatialization is enabled.
361
+ * @return [Boolean]
362
+ * @!method spatialization_enabled=(value)
363
+ * Enables or disables 3D spatialization.
364
+ * @return [Boolean]
365
+ * @!method position
366
+ * Returns the source's position in 3D space.
367
+ * @return [Vector3]
368
+ * @!method position=(value)
369
+ * Sets the source's position in 3D space.
370
+ * @return [Vector3]
371
+ * @!method direction
372
+ * Returns the direction the source is facing.
373
+ * @return [Vector3]
374
+ * @!method direction=(value)
375
+ * Sets the direction the source is facing.
376
+ * @return [Vector3]
377
+ * @!method velocity
378
+ * Returns the source's velocity, used for Doppler calculations.
379
+ * @return [Vector3]
380
+ * @!method velocity=(value)
381
+ * Sets the source's velocity for Doppler calculations.
382
+ * @return [Vector3]
383
+ * @!method cone
384
+ * Returns the source's directional attenuation cone.
385
+ * @return [SoundSourceCone]
386
+ * @!method cone=(value)
387
+ * Sets the source's directional attenuation cone.
388
+ * @return [SoundSourceCone]
389
+ * @!method doppler_factor
390
+ * Returns the factor by which the Doppler effect is scaled.
391
+ * @return [Float]
392
+ * @!method doppler_factor=(value)
393
+ * Sets the factor by which the Doppler effect is scaled.
394
+ * @return [Float]
395
+ * @!method directional_attenuation_factor
396
+ * Returns the factor controlling directional attenuation.
397
+ * @return [Float]
398
+ * @!method directional_attenuation_factor=(value)
399
+ * Sets the factor controlling directional attenuation.
400
+ * @return [Float]
401
+ * @!method relative_to_listener?
402
+ * Returns +true+ if the source is positioned relative to the listener.
403
+ * @return [Boolean]
404
+ * @!method relative_to_listener=(value)
405
+ * Makes the source relative to, or independent of, the listener.
406
+ * @return [Boolean]
407
+ * @!method min_distance
408
+ * Returns the minimum distance of the distance-attenuation model.
409
+ * @return [Float]
410
+ * @!method min_distance=(value)
411
+ * Sets the minimum distance of the distance-attenuation model.
412
+ * @return [Float]
413
+ * @!method max_distance
414
+ * Returns the maximum distance of the distance-attenuation model.
415
+ * @return [Float]
416
+ * @!method max_distance=(value)
417
+ * Sets the maximum distance of the distance-attenuation model.
418
+ * @return [Float]
419
+ * @!method min_gain
420
+ * Returns the minimum gain of the distance-attenuation model.
421
+ * @return [Float]
422
+ * @!method min_gain=(value)
423
+ * Sets the minimum gain of the distance-attenuation model.
424
+ * @return [Float]
425
+ * @!method max_gain
426
+ * Returns the maximum gain of the distance-attenuation model.
427
+ * @return [Float]
428
+ * @!method max_gain=(value)
429
+ * Sets the maximum gain of the distance-attenuation model.
430
+ * @return [Float]
431
+ * @!method attenuation
432
+ * Returns the distance-attenuation factor.
433
+ * @return [Float]
434
+ * @!method attenuation=(value)
435
+ * Sets the distance-attenuation factor.
436
+ * @return [Float]
437
+ * @!method playing_offset
438
+ * Returns the current playing offset.
439
+ * @return [Time]
440
+ * @!method playing_offset=(value)
441
+ * Seeks to the given playing offset.
442
+ * @return [Time]
443
+ * @!method effect_processor=(proc)
444
+ * Installs a Proc that post-processes this source's audio in real time.
445
+ * @return [Proc] +proc+
446
+ */
447
+ void Init_SoundStream(VALUE rb_mSFML) {
448
+ rb_cSoundStream = rb_define_class_under(rb_mSFML, "SoundStream", rb_cObject);
276
449
 
277
450
  rb_define_singleton_method(rb_cSoundStream, "new", SoundStream_new, -1);
278
451
 
@@ -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
@@ -84,6 +84,10 @@
84
84
 
85
85
  static VALUE rb_mExt;
86
86
 
87
+ /* Document-module: SFML
88
+ * Ruby bindings for SFML 3, via its C API, CSFML. Every class and module in
89
+ * this library lives under this namespace.
90
+ */
87
91
  void Init_sfml_ext(void) {
88
92
  rb_mExt = rb_define_module("SFML");
89
93