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
@@ -1,33 +1,48 @@
1
1
  #include "audio/sound_recorder.h"
2
2
 
3
3
  #include <ruby.h>
4
- #include <ruby/thread.h>
5
4
  #include <stdint.h>
6
5
  #include <stdlib.h>
7
6
 
8
7
  #include "audio/audio_enums.h"
8
+ #include "core/foreign_thread.h"
9
9
  #include "core/macros.h"
10
10
 
11
- /* A subclassable recorder. The capture callbacks arrive on SFML's audio
12
- thread, so each re-enters Ruby through rb_thread_call_with_gvl and treats an
13
- exception as "stop capturing" instead of unwinding into the audio engine.
14
- A subclass only has to implement #on_process; #on_start and #on_stop are
15
- optional and default to continuing. */
11
+ /* A subclassable recorder. The capture callbacks arrive on SFML's capture
12
+ thread -- a real OS thread never created by Ruby, exactly like the audio
13
+ playback thread effect_processor.c/sound_stream.c are built to handle --
14
+ so re-entering Ruby directly (e.g. via rb_thread_call_with_gvl, as this
15
+ file previously did for #on_process, or via rb_protect with no GVL
16
+ handling at all, as it previously did for #on_start/#on_stop) is a fatal
17
+ VM error. Every callback here instead posts its work to the shared
18
+ foreign-thread worker (core/foreign_thread.h), the same mechanism the
19
+ other two files use, and treats an exception as "stop capturing" rather
20
+ than unwinding into the audio engine. A subclass only has to implement
21
+ #on_process; #on_start and #on_stop are optional and default to
22
+ continuing. */
23
+
24
+ #define SOUND_RECORDER_JOB_TIMEOUT_MS 50
16
25
  typedef struct {
17
26
  VALUE rb_self;
18
- sfSoundRecorder *handle;
27
+ sfSoundRecorder* handle;
19
28
  } SoundRecorder;
20
29
 
21
30
  static VALUE rb_cSoundRecorder;
22
31
 
23
- static void SoundRecorder_mark(void *ptr) {
24
- SoundRecorder *recorder = ptr;
32
+ /* CSFML reports "no such device" as NULL; that is an absent name, not an
33
+ error, so it maps to nil rather than raising out of rb_str_new_cstr. */
34
+ static VALUE SoundRecorder_nullable_string(const char* value) {
35
+ return value == NULL ? Qnil : rb_str_new_cstr(value);
36
+ }
37
+
38
+ static void SoundRecorder_mark(void* ptr) {
39
+ SoundRecorder* recorder = ptr;
25
40
 
26
41
  rb_gc_mark(recorder->rb_self);
27
42
  }
28
43
 
29
- static void SoundRecorder_free(void *ptr) {
30
- SoundRecorder *recorder = ptr;
44
+ static void SoundRecorder_free(void* ptr) {
45
+ SoundRecorder* recorder = ptr;
31
46
 
32
47
  if (recorder->handle != NULL) {
33
48
  sfSoundRecorder_destroy(recorder->handle);
@@ -39,8 +54,7 @@ static void SoundRecorder_free(void *ptr) {
39
54
  static const rb_data_type_t SoundRecorder_data_type = {
40
55
  .wrap_struct_name = "SFML::SoundRecorder",
41
56
  .function = {.dmark = SoundRecorder_mark, .dfree = SoundRecorder_free, .dsize = NULL},
42
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
43
- };
57
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
44
58
 
45
59
  typedef struct {
46
60
  VALUE self;
@@ -48,25 +62,31 @@ typedef struct {
48
62
  } InvokeContext;
49
63
 
50
64
  static VALUE SoundRecorder_invoke_body(VALUE raw) {
51
- InvokeContext *ctx = (InvokeContext *) raw;
65
+ InvokeContext* ctx = (InvokeContext*)raw;
52
66
 
53
67
  return rb_funcall(ctx->self, ctx->method, 0);
54
68
  }
55
69
 
56
- /* Calls a zero-argument Ruby method, swallowing any exception it raises. */
57
- static void SoundRecorder_invoke(VALUE self, ID method) {
58
- InvokeContext ctx = {.self = self, .method = method};
70
+ /* Runs on the shared foreign-thread worker, which holds the GVL. */
71
+ static void SoundRecorder_invoke_run(void* raw) {
59
72
  int state = 0;
60
73
 
61
- rb_protect(SoundRecorder_invoke_body, (VALUE) &ctx, &state);
74
+ rb_protect(SoundRecorder_invoke_body, (VALUE)raw, &state);
62
75
 
63
76
  if (state) {
64
77
  rb_set_errinfo(Qnil);
65
78
  }
66
79
  }
67
80
 
68
- static bool SoundRecorder_on_start(void *userData) {
69
- SoundRecorder *recorder = userData;
81
+ /* Calls a zero-argument Ruby method, swallowing any exception it raises. */
82
+ static void SoundRecorder_invoke(VALUE self, ID method) {
83
+ InvokeContext ctx = {.self = self, .method = method};
84
+
85
+ run_on_ruby_thread(SoundRecorder_invoke_run, &ctx, SOUND_RECORDER_JOB_TIMEOUT_MS);
86
+ }
87
+
88
+ static bool SoundRecorder_on_start(void* userData) {
89
+ SoundRecorder* recorder = userData;
70
90
 
71
91
  if (rb_respond_to(recorder->rb_self, rb_intern("on_start"))) {
72
92
  SoundRecorder_invoke(recorder->rb_self, rb_intern("on_start"));
@@ -76,15 +96,15 @@ static bool SoundRecorder_on_start(void *userData) {
76
96
  }
77
97
 
78
98
  typedef struct {
79
- SoundRecorder *recorder;
80
- const int16_t *samples;
99
+ SoundRecorder* recorder;
100
+ const int16_t* samples;
81
101
  size_t sample_count;
82
102
  int ok;
83
103
  } ProcessContext;
84
104
 
85
105
  static VALUE SoundRecorder_process_body(VALUE raw) {
86
- ProcessContext *ctx = (ProcessContext *) raw;
87
- VALUE rb_samples = rb_ary_new_capa((long) ctx->sample_count);
106
+ ProcessContext* ctx = (ProcessContext*)raw;
107
+ VALUE rb_samples = rb_ary_new_capa((long)ctx->sample_count);
88
108
  VALUE result;
89
109
  size_t i;
90
110
 
@@ -98,41 +118,58 @@ static VALUE SoundRecorder_process_body(VALUE raw) {
98
118
  return Qnil;
99
119
  }
100
120
 
101
- static void *SoundRecorder_process_gvl(void *raw) {
121
+ /* Runs on the shared foreign-thread worker, which holds the GVL. */
122
+ static void SoundRecorder_process_run(void* raw) {
102
123
  int state = 0;
103
124
 
104
- rb_protect(SoundRecorder_process_body, (VALUE) raw, &state);
125
+ rb_protect(SoundRecorder_process_body, (VALUE)raw, &state);
105
126
 
106
127
  if (state) {
107
128
  rb_set_errinfo(Qnil);
108
- ((ProcessContext *) raw)->ok = 0;
129
+ ((ProcessContext*)raw)->ok = 0;
109
130
  }
110
-
111
- return NULL;
112
131
  }
113
132
 
114
- static bool SoundRecorder_on_process(const int16_t *samples, size_t sample_count, void *userData) {
115
- SoundRecorder *recorder = userData;
133
+ static bool SoundRecorder_on_process(const int16_t* samples, size_t sample_count, void* userData) {
134
+ SoundRecorder* recorder = userData;
116
135
  ProcessContext ctx = {
117
- .recorder = recorder, .samples = samples, .sample_count = sample_count, .ok = 0
118
- };
119
-
120
- rb_thread_call_with_gvl(SoundRecorder_process_gvl, &ctx);
136
+ .recorder = recorder, .samples = samples, .sample_count = sample_count, .ok = 0};
137
+
138
+ if (!run_on_ruby_thread(SoundRecorder_process_run, &ctx, SOUND_RECORDER_JOB_TIMEOUT_MS)) {
139
+ /* Timed out before the worker even claimed the job (e.g. GVL
140
+ contention): drop this one chunk rather than block the capture
141
+ thread indefinitely, but keep recording rather than aborting the
142
+ whole session over one missed callback. */
143
+ return true;
144
+ }
121
145
 
122
146
  return ctx.ok ? true : false;
123
147
  }
124
148
 
125
- static void SoundRecorder_on_stop(void *userData) {
126
- SoundRecorder *recorder = userData;
149
+ static void SoundRecorder_on_stop(void* userData) {
150
+ SoundRecorder* recorder = userData;
127
151
 
128
152
  if (rb_respond_to(recorder->rb_self, rb_intern("on_stop"))) {
129
153
  SoundRecorder_invoke(recorder->rb_self, rb_intern("on_stop"));
130
154
  }
131
155
  }
132
156
 
157
+ /* call-seq:
158
+ * SoundRecorder.new -> SoundRecorder
159
+ *
160
+ * SoundRecorder must be subclassed: the subclass is required to implement
161
+ * +#on_process(samples)+, called from the audio thread with an Array of
162
+ * captured Integer samples whenever a chunk is ready (return a truthy value
163
+ * to keep recording, falsy to stop), and may optionally implement
164
+ * +#on_start+ and +#on_stop+.
165
+ *
166
+ * @return [SoundRecorder]
167
+ * @raise [NotImplementedError] if the subclass does not define #on_process
168
+ * @raise [RuntimeError] if no capture device is available
169
+ */
133
170
  static VALUE SoundRecorder_new(VALUE klass) {
134
- SoundRecorder *ptr;
135
- sfSoundRecorder *handle;
171
+ SoundRecorder* ptr;
172
+ sfSoundRecorder* handle;
136
173
  VALUE self;
137
174
 
138
175
  ptr = malloc(sizeof(SoundRecorder));
@@ -160,27 +197,59 @@ static VALUE SoundRecorder_new(VALUE klass) {
160
197
  return self;
161
198
  }
162
199
 
200
+ /* call-seq:
201
+ * start(sample_rate) -> true or false
202
+ *
203
+ * Starts capturing audio at the given sample rate.
204
+ *
205
+ * @return [Boolean] whether recording started successfully
206
+ */
163
207
  static VALUE SoundRecorder_start(VALUE self, VALUE rb_sample_rate) {
164
208
  return BOOL2RB(sfSoundRecorder_start(Get_SoundRecorder_Struct(self),
165
- (unsigned int) NUM2INT(rb_sample_rate)));
209
+ (unsigned int)NUM2INT(rb_sample_rate)));
166
210
  }
167
211
 
212
+ /* call-seq: stop -> self
213
+ *
214
+ * Stops capturing audio.
215
+ *
216
+ * @return [self]
217
+ */
168
218
  static VALUE SoundRecorder_stop(VALUE self) {
169
219
  sfSoundRecorder_stop(Get_SoundRecorder_Struct(self));
170
220
  return self;
171
221
  }
172
222
 
223
+ /* call-seq: sample_rate -> Integer
224
+ *
225
+ * Returns the sample rate used for capture.
226
+ *
227
+ * @return [Integer]
228
+ */
173
229
  static VALUE SoundRecorder_sample_rate(VALUE self) {
174
230
  return UINT2NUM(sfSoundRecorder_getSampleRate(Get_SoundRecorder_Struct(self)));
175
231
  }
176
232
 
233
+ /* call-seq: SoundRecorder.available? -> true or false
234
+ *
235
+ * Returns +true+ if the audio backend supports capture.
236
+ *
237
+ * @return [Boolean] whether the audio backend supports capture at all
238
+ */
177
239
  static VALUE SoundRecorder_available(VALUE klass) {
178
240
  return BOOL2RB(sfSoundRecorder_isAvailable());
179
241
  }
180
242
 
243
+ /* call-seq: SoundRecorder.available_devices -> Array<String>
244
+ *
245
+ * Returns the names of the capture devices available on this system.
246
+ *
247
+ * @return [Array<String>] names of the capture devices available on this
248
+ * system
249
+ */
181
250
  static VALUE SoundRecorder_available_devices(VALUE klass) {
182
251
  size_t count = 0;
183
- const char *const *devices = sfSoundRecorder_getAvailableDevices(&count);
252
+ const char* const* devices = sfSoundRecorder_getAvailableDevices(&count);
184
253
  VALUE rb_array;
185
254
  size_t i;
186
255
 
@@ -188,7 +257,7 @@ static VALUE SoundRecorder_available_devices(VALUE klass) {
188
257
  return rb_ary_new();
189
258
  }
190
259
 
191
- rb_array = rb_ary_new_capa((long) count);
260
+ rb_array = rb_ary_new_capa((long)count);
192
261
 
193
262
  for (i = 0; i < count; i++) {
194
263
  rb_ary_push(rb_array, rb_str_new_cstr(devices[i]));
@@ -197,31 +266,74 @@ static VALUE SoundRecorder_available_devices(VALUE klass) {
197
266
  return rb_array;
198
267
  }
199
268
 
269
+ /* call-seq: SoundRecorder.default_device -> String or nil
270
+ *
271
+ * Returns the name of the system's default capture device.
272
+ *
273
+ * @return [String, nil] the name of the system's default capture device, or
274
+ * +nil+ when the system reports none
275
+ */
200
276
  static VALUE SoundRecorder_default_device(VALUE klass) {
201
- return rb_str_new_cstr(sfSoundRecorder_getDefaultDevice());
277
+ return SoundRecorder_nullable_string(sfSoundRecorder_getDefaultDevice());
202
278
  }
203
279
 
280
+ /* call-seq: device -> String or nil
281
+ *
282
+ * Returns the name of the capture device in use.
283
+ *
284
+ * @return [String, nil] the name of the capture device in use, or +nil+ when
285
+ * the recorder has none
286
+ */
204
287
  static VALUE SoundRecorder_device(VALUE self) {
205
- return rb_str_new_cstr(sfSoundRecorder_getDevice(Get_SoundRecorder_Struct(self)));
288
+ return SoundRecorder_nullable_string(sfSoundRecorder_getDevice(Get_SoundRecorder_Struct(self)));
206
289
  }
207
290
 
291
+ /* call-seq:
292
+ * device=(value) -> true or false
293
+ *
294
+ * Must be called while not recording. Get available names from
295
+ * .available_devices.
296
+ *
297
+ * @return [Boolean] whether the device was set successfully
298
+ */
208
299
  static VALUE SoundRecorder_set_device(VALUE self, VALUE rb_name) {
209
300
  return BOOL2RB(
210
301
  sfSoundRecorder_setDevice(Get_SoundRecorder_Struct(self), StringValueCStr(rb_name)));
211
302
  }
212
303
 
304
+ /* call-seq: channel_count -> Integer
305
+ *
306
+ * Returns the number of capture channels.
307
+ *
308
+ * @return [Integer]
309
+ */
213
310
  static VALUE SoundRecorder_channel_count(VALUE self) {
214
311
  return UINT2NUM(sfSoundRecorder_getChannelCount(Get_SoundRecorder_Struct(self)));
215
312
  }
216
313
 
314
+ /* call-seq:
315
+ * channel_count=(value) -> Integer
316
+ *
317
+ * Must be called while not recording.
318
+ *
319
+ * @return [Integer] +value+
320
+ */
217
321
  static VALUE SoundRecorder_set_channel_count(VALUE self, VALUE rb_count) {
218
- sfSoundRecorder_setChannelCount(Get_SoundRecorder_Struct(self), (unsigned int) NUM2INT(rb_count));
322
+ sfSoundRecorder_setChannelCount(Get_SoundRecorder_Struct(self),
323
+ (unsigned int)NUM2INT(rb_count));
219
324
  return rb_count;
220
325
  }
221
326
 
327
+ /* call-seq: channel_map -> Array<Symbol>
328
+ *
329
+ * Returns the channel layout of the recorder.
330
+ *
331
+ * @return [Array<Symbol>] one entry per channel, e.g.
332
+ * +[:front_left, :front_right]+
333
+ */
222
334
  static VALUE SoundRecorder_channel_map(VALUE self) {
223
335
  size_t count = 0;
224
- sfSoundChannel *map = sfSoundRecorder_getChannelMap(Get_SoundRecorder_Struct(self), &count);
336
+ sfSoundChannel* map = sfSoundRecorder_getChannelMap(Get_SoundRecorder_Struct(self), &count);
225
337
  VALUE rb_array;
226
338
  size_t i;
227
339
 
@@ -229,7 +341,7 @@ static VALUE SoundRecorder_channel_map(VALUE self) {
229
341
  return rb_ary_new();
230
342
  }
231
343
 
232
- rb_array = rb_ary_new_capa((long) count);
344
+ rb_array = rb_ary_new_capa((long)count);
233
345
 
234
346
  for (i = 0; i < count; i++) {
235
347
  rb_ary_push(rb_array, ID2SYM(rb_intern(sound_channel_name(map[i]))));
@@ -238,14 +350,22 @@ static VALUE SoundRecorder_channel_map(VALUE self) {
238
350
  return rb_array;
239
351
  }
240
352
 
241
- void Init_SoundRecorder(VALUE rb_module) {
242
- rb_cSoundRecorder = rb_define_class_under(rb_module, "SoundRecorder", rb_cObject);
353
+ /* Document-class: SFML::SoundRecorder
354
+ * Base class for a custom audio capture consumer. Subclasses must implement
355
+ * +#on_process(samples)+, called from the audio thread whenever a chunk of
356
+ * captured samples is ready, and may implement +#on_start+/+#on_stop+ to
357
+ * react to recording starting/stopping. For simply capturing into a
358
+ * SoundBuffer without custom processing, use SoundBufferRecorder instead.
359
+ */
360
+ void Init_SoundRecorder(VALUE rb_mSFML) {
361
+ rb_cSoundRecorder = rb_define_class_under(rb_mSFML, "SoundRecorder", rb_cObject);
243
362
 
244
363
  rb_define_singleton_method(rb_cSoundRecorder, "new", SoundRecorder_new, 0);
245
364
  rb_define_singleton_method(rb_cSoundRecorder, "available?", SoundRecorder_available, 0);
246
365
  rb_define_singleton_method(rb_cSoundRecorder, "available_devices",
247
366
  SoundRecorder_available_devices, 0);
248
- rb_define_singleton_method(rb_cSoundRecorder, "default_device", SoundRecorder_default_device, 0);
367
+ rb_define_singleton_method(rb_cSoundRecorder, "default_device", SoundRecorder_default_device,
368
+ 0);
249
369
 
250
370
  rb_define_method(rb_cSoundRecorder, "start", SoundRecorder_start, 1);
251
371
  rb_define_method(rb_cSoundRecorder, "stop", SoundRecorder_stop, 0);
@@ -261,8 +381,8 @@ VALUE Get_Klass_SoundRecorder(void) {
261
381
  return rb_cSoundRecorder;
262
382
  }
263
383
 
264
- void *Get_SoundRecorder_Struct(VALUE self) {
265
- SoundRecorder *ptr;
384
+ void* Get_SoundRecorder_Struct(VALUE self) {
385
+ SoundRecorder* ptr;
266
386
  TypedData_Get_Struct(self, SoundRecorder, &SoundRecorder_data_type, ptr);
267
387
  return ptr->handle;
268
388
  }
@@ -12,84 +12,165 @@ 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
 
32
+ /* call-seq:
33
+ * SoundSourceCone.new(inner_angle, outer_angle, outer_gain) -> SoundSourceCone
34
+ *
35
+ * Creates a directional attenuation cone with the given angles and gain.
36
+ *
37
+ * @return [SoundSourceCone]
38
+ */
33
39
  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
- };
40
+ sfSoundSourceCone cone = {.innerAngle = (float)NUM2DBL(rb_inner),
41
+ .outerAngle = (float)NUM2DBL(rb_outer),
42
+ .outerGain = (float)NUM2DBL(rb_gain)};
39
43
 
40
44
  return SoundSourceCone_wrap(cone);
41
45
  }
42
46
 
47
+ /* call-seq: inner_angle -> Float
48
+ *
49
+ * Returns the inner cone angle in degrees.
50
+ *
51
+ * @return [Float] angle, in degrees, of the inner cone within which the
52
+ * source is heard at full volume
53
+ */
43
54
  static VALUE SoundSourceCone_get_inner_angle(VALUE self) {
44
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.innerAngle);
55
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.innerAngle);
45
56
  }
46
57
 
58
+ /* call-seq: outer_angle -> Float
59
+ *
60
+ * Returns the outer cone angle in degrees.
61
+ *
62
+ * @return [Float] angle, in degrees, of the outer cone beyond which the
63
+ * source is heard at +outer_gain+ volume
64
+ */
47
65
  static VALUE SoundSourceCone_get_outer_angle(VALUE self) {
48
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerAngle);
66
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerAngle);
49
67
  }
50
68
 
69
+ /* call-seq: outer_gain -> Float
70
+ *
71
+ * Returns the gain applied outside the outer cone.
72
+ *
73
+ * @return [Float] volume factor applied outside the outer cone
74
+ */
51
75
  static VALUE SoundSourceCone_get_outer_gain(VALUE self) {
52
- return DBL2NUM(((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerGain);
76
+ return DBL2NUM(((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerGain);
53
77
  }
54
78
 
79
+ /* call-seq:
80
+ * inner_angle=(value) -> Float
81
+ *
82
+ * Sets the inner cone angle in degrees.
83
+ *
84
+ * @return [Float] +value+
85
+ */
55
86
  static VALUE SoundSourceCone_set_inner_angle(VALUE self, VALUE rb_value) {
56
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.innerAngle = (float) NUM2DBL(rb_value);
87
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.innerAngle =
88
+ (float)NUM2DBL(rb_value);
57
89
  return rb_value;
58
90
  }
59
91
 
92
+ /* call-seq:
93
+ * outer_angle=(value) -> Float
94
+ *
95
+ * Sets the outer cone angle in degrees.
96
+ *
97
+ * @return [Float] +value+
98
+ */
60
99
  static VALUE SoundSourceCone_set_outer_angle(VALUE self, VALUE rb_value) {
61
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerAngle = (float) NUM2DBL(rb_value);
100
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerAngle =
101
+ (float)NUM2DBL(rb_value);
62
102
  return rb_value;
63
103
  }
64
104
 
105
+ /* call-seq:
106
+ * outer_gain=(value) -> Float
107
+ *
108
+ * Sets the gain applied outside the outer cone.
109
+ *
110
+ * @return [Float] +value+
111
+ */
65
112
  static VALUE SoundSourceCone_set_outer_gain(VALUE self, VALUE rb_value) {
66
- ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone.outerGain = (float) NUM2DBL(rb_value);
113
+ ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone.outerGain = (float)NUM2DBL(rb_value);
67
114
  return rb_value;
68
115
  }
69
116
 
117
+ /* call-seq: to_a -> [Float, Float, Float]
118
+ *
119
+ * Returns the cone's three components as an Array.
120
+ *
121
+ * @return [Array<Float>] +[inner_angle, outer_angle, outer_gain]+
122
+ */
70
123
  static VALUE SoundSourceCone_to_a(VALUE self) {
71
- sfSoundSourceCone cone = ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone;
124
+ sfSoundSourceCone cone = ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone;
72
125
 
73
126
  return rb_ary_new_from_args(3, DBL2NUM(cone.innerAngle), DBL2NUM(cone.outerAngle),
74
127
  DBL2NUM(cone.outerGain));
75
128
  }
76
129
 
130
+ /* call-seq:
131
+ * self == other -> true or false
132
+ *
133
+ * Returns +true+ if +other+ is a cone with the same angles and gain.
134
+ *
135
+ * @return [Boolean]
136
+ */
77
137
  static VALUE SoundSourceCone_eql(VALUE self, VALUE rb_other) {
78
- sfSoundSourceCone a = ((SoundSourceCone *) Get_SoundSourceCone_Struct(self))->cone;
138
+ sfSoundSourceCone a = ((SoundSourceCone*)Get_SoundSourceCone_Struct(self))->cone;
79
139
  sfSoundSourceCone b;
80
140
 
81
141
  if (!rb_obj_is_kind_of(rb_other, rb_cSoundSourceCone)) {
82
142
  return Qfalse;
83
143
  }
84
144
 
85
- b = ((SoundSourceCone *) Get_SoundSourceCone_Struct(rb_other))->cone;
145
+ b = ((SoundSourceCone*)Get_SoundSourceCone_Struct(rb_other))->cone;
86
146
 
87
147
  return BOOL2RB(a.innerAngle == b.innerAngle && a.outerAngle == b.outerAngle &&
88
148
  a.outerGain == b.outerGain);
89
149
  }
90
150
 
91
- void Init_SoundSourceCone(VALUE rb_module) {
92
- rb_cSoundSourceCone = rb_define_class_under(rb_module, "SoundSourceCone", rb_cObject);
151
+ /* Document-class: SFML::SoundSourceCone
152
+ * A directional attenuation cone for a SoundSource (SoundSource#cone) or the
153
+ * Listener (Listener.cone): within +inner_angle+ degrees of the facing
154
+ * direction the source is heard at full volume; beyond +outer_angle+
155
+ * degrees it is heard at +outer_gain+ volume, with a smooth transition in
156
+ * between.
157
+ *
158
+ * @!attribute inner_angle
159
+ * Angle, in degrees, of the inner cone within which the source is heard at
160
+ * full volume.
161
+ * @return [Float] angle, in degrees, of the inner cone within which the
162
+ * source is heard at full volume
163
+ * @!attribute outer_angle
164
+ * Angle, in degrees, of the outer cone beyond which the source is heard at
165
+ * +outer_gain+ volume.
166
+ * @return [Float] angle, in degrees, of the outer cone beyond which the
167
+ * source is heard at +outer_gain+ volume
168
+ * @!attribute outer_gain
169
+ * Volume factor applied outside the outer cone.
170
+ * @return [Float] volume factor applied outside the outer cone
171
+ */
172
+ void Init_SoundSourceCone(VALUE rb_mSFML) {
173
+ rb_cSoundSourceCone = rb_define_class_under(rb_mSFML, "SoundSourceCone", rb_cObject);
93
174
 
94
175
  rb_define_singleton_method(rb_cSoundSourceCone, "new", SoundSourceCone_new, 3);
95
176
 
@@ -107,30 +188,28 @@ VALUE Get_Klass_SoundSourceCone(void) {
107
188
  return rb_cSoundSourceCone;
108
189
  }
109
190
 
110
- void *Get_SoundSourceCone_Struct(VALUE self) {
111
- SoundSourceCone *ptr;
191
+ void* Get_SoundSourceCone_Struct(VALUE self) {
192
+ SoundSourceCone* ptr;
112
193
  TypedData_Get_Struct(self, SoundSourceCone, &SoundSourceCone_data_type, ptr);
113
194
  return ptr;
114
195
  }
115
196
 
116
197
  sfSoundSourceCone sound_source_cone_from_rb(VALUE rb_cone) {
117
198
  if (rb_obj_is_kind_of(rb_cone, rb_cSoundSourceCone)) {
118
- return ((SoundSourceCone *) Get_SoundSourceCone_Struct(rb_cone))->cone;
199
+ return ((SoundSourceCone*)Get_SoundSourceCone_Struct(rb_cone))->cone;
119
200
  }
120
201
 
121
202
  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
- };
203
+ sfSoundSourceCone cone = {.innerAngle = (float)NUM2DBL(rb_ary_entry(rb_cone, 0)),
204
+ .outerAngle = (float)NUM2DBL(rb_ary_entry(rb_cone, 1)),
205
+ .outerGain = (float)NUM2DBL(rb_ary_entry(rb_cone, 2))};
127
206
 
128
207
  return cone;
129
208
  }
130
209
 
131
210
  raise_invalid_argument_class(rb_cSoundSourceCone);
132
211
 
133
- return (sfSoundSourceCone) {0.0f, 0.0f, 0.0f};
212
+ return (sfSoundSourceCone){0.0f, 0.0f, 0.0f};
134
213
  }
135
214
 
136
215
  VALUE sound_source_cone_to_rb(sfSoundSourceCone cone) {