sfml3-rb 0.0.1 → 0.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +342 -0
- data/README.md +51 -14
- data/TODO.md +199 -0
- data/ext/audio/audio_enums.c +131 -0
- data/ext/audio/audio_enums.h +18 -0
- data/ext/audio/effect_processor.c +233 -0
- data/ext/audio/effect_processor.h +25 -0
- data/ext/audio/listener.c +83 -0
- data/ext/audio/listener.h +8 -0
- data/ext/audio/music.c +174 -0
- data/ext/audio/music.h +14 -0
- data/ext/audio/sound.c +139 -0
- data/ext/audio/sound.h +14 -0
- data/ext/audio/sound_buffer.c +274 -0
- data/ext/audio/sound_buffer.h +18 -0
- data/ext/audio/sound_buffer_recorder.c +109 -0
- data/ext/audio/sound_buffer_recorder.h +14 -0
- data/ext/audio/sound_recorder.c +268 -0
- data/ext/audio/sound_recorder.h +14 -0
- data/ext/audio/sound_source.h +13 -0
- data/ext/audio/sound_source.inc +271 -0
- data/ext/audio/sound_source_cone.c +138 -0
- data/ext/audio/sound_source_cone.h +20 -0
- data/ext/audio/sound_stream.c +294 -0
- data/ext/audio/sound_stream.h +14 -0
- data/ext/{exceptions.c → core/exceptions.c} +10 -8
- data/ext/{ext → core}/exceptions.h +3 -3
- data/ext/core/foreign_thread.c +149 -0
- data/ext/core/foreign_thread.h +31 -0
- data/ext/core/macros.h +8 -0
- data/ext/{ext → core}/sfml.h +5 -3
- data/ext/core/unicode.c +46 -0
- data/ext/core/unicode.h +25 -0
- data/ext/ext.c +125 -14
- data/ext/extconf.rb +51 -6
- data/ext/graphics/blend_mode.c +261 -0
- data/ext/graphics/blend_mode.h +18 -0
- data/ext/graphics/circle.c +319 -0
- data/ext/{ext/klass/drawable → graphics}/circle.h +3 -3
- data/ext/graphics/color.c +318 -0
- data/ext/graphics/color.h +37 -0
- data/ext/{drawable.c → graphics/drawable.c} +11 -11
- data/ext/graphics/drawable.h +10 -0
- data/ext/graphics/enums.c +123 -0
- data/ext/graphics/enums.h +20 -0
- data/ext/graphics/font.c +148 -0
- data/ext/graphics/font.h +14 -0
- data/ext/graphics/glyph.c +60 -0
- data/ext/graphics/glyph.h +14 -0
- data/ext/graphics/image.c +205 -0
- data/ext/graphics/image.h +16 -0
- data/ext/graphics/polygon.c +300 -0
- data/ext/graphics/polygon.h +10 -0
- data/ext/graphics/rect.c +287 -0
- data/ext/graphics/rect.h +30 -0
- data/ext/graphics/rectangle.c +302 -0
- data/ext/graphics/rectangle.h +10 -0
- data/ext/graphics/render_state.c +204 -0
- data/ext/graphics/render_state.h +18 -0
- data/ext/graphics/render_target.inc +181 -0
- data/ext/graphics/render_texture.c +182 -0
- data/ext/graphics/render_texture.h +14 -0
- data/ext/graphics/shader.c +540 -0
- data/ext/graphics/shader.h +14 -0
- data/ext/graphics/shape.c +311 -0
- data/ext/graphics/shape.h +10 -0
- data/ext/graphics/sprite.c +249 -0
- data/ext/graphics/sprite.h +10 -0
- data/ext/graphics/stencil_mode.c +211 -0
- data/ext/graphics/stencil_mode.h +18 -0
- data/ext/graphics/target.c +133 -0
- data/ext/graphics/target.h +40 -0
- data/ext/graphics/text.c +344 -0
- data/ext/graphics/text.h +10 -0
- data/ext/graphics/texture.c +379 -0
- data/ext/graphics/texture.h +16 -0
- data/ext/graphics/transform.c +372 -0
- data/ext/graphics/transform.h +35 -0
- data/ext/{transformable.c → graphics/transformable.c} +168 -144
- data/ext/{ext/klass → graphics}/transformable.h +3 -3
- data/ext/graphics/vertex.c +179 -0
- data/ext/graphics/vertex.h +23 -0
- data/ext/graphics/vertex_array.c +127 -0
- data/ext/graphics/vertex_array.h +10 -0
- data/ext/graphics/vertex_buffer.c +211 -0
- data/ext/graphics/vertex_buffer.h +14 -0
- data/ext/{view.c → graphics/view.c} +168 -169
- data/ext/{ext/klass → graphics}/view.h +3 -3
- data/ext/network/ftp.c +405 -0
- data/ext/network/ftp.h +20 -0
- data/ext/network/http.c +243 -0
- data/ext/network/http.h +18 -0
- data/ext/network/ip_address.c +164 -0
- data/ext/network/ip_address.h +20 -0
- data/ext/network/network_enums.c +298 -0
- data/ext/network/network_enums.h +26 -0
- data/ext/network/packet.c +189 -0
- data/ext/network/packet.h +14 -0
- data/ext/network/socket_selector.c +142 -0
- data/ext/network/socket_selector.h +14 -0
- data/ext/network/tcp_listener.c +115 -0
- data/ext/network/tcp_listener.h +14 -0
- data/ext/network/tcp_socket.c +199 -0
- data/ext/network/tcp_socket.h +17 -0
- data/ext/network/udp_socket.c +190 -0
- data/ext/network/udp_socket.h +14 -0
- data/ext/ports.rb +97 -21
- data/ext/system/buffer.c +77 -0
- data/ext/system/buffer.h +14 -0
- data/ext/system/clock.c +100 -0
- data/ext/{ext/klass → system}/clock.h +3 -3
- data/ext/system/input_stream.c +229 -0
- data/ext/system/input_stream.h +23 -0
- data/ext/system/sleep.c +16 -0
- data/ext/system/sleep.h +8 -0
- data/ext/system/time.c +218 -0
- data/ext/system/time.h +18 -0
- data/ext/system/vec2.c +251 -0
- data/ext/system/vec2.h +55 -0
- data/ext/system/vec3.c +219 -0
- data/ext/system/vec3.h +18 -0
- data/ext/window/clipboard.c +89 -0
- data/ext/window/clipboard.h +8 -0
- data/ext/window/context.c +70 -0
- data/ext/window/context.h +8 -0
- data/ext/window/context_settings.c +220 -0
- data/ext/window/context_settings.h +18 -0
- data/ext/window/cursor.c +56 -0
- data/ext/window/cursor.h +14 -0
- data/ext/window/event.c +216 -0
- data/ext/window/event.h +14 -0
- data/ext/{event_name.c → window/event_name.c} +2 -2
- data/ext/window/event_name.h +8 -0
- data/ext/window/input_enums.c +261 -0
- data/ext/window/input_enums.h +36 -0
- data/ext/window/joystick.c +60 -0
- data/ext/window/joystick.h +8 -0
- data/ext/{keyboard.c → window/keyboard.c} +74 -2
- data/ext/window/keyboard.h +12 -0
- data/ext/window/mouse.c +70 -0
- data/ext/window/mouse.h +8 -0
- data/ext/window/sensor.c +30 -0
- data/ext/window/sensor.h +8 -0
- data/ext/window/touch.c +49 -0
- data/ext/window/touch.h +8 -0
- data/ext/window/video_mode.c +133 -0
- data/ext/window/video_mode.h +14 -0
- data/ext/window/vulkan.c +44 -0
- data/ext/window/vulkan.h +8 -0
- data/ext/window/window.c +414 -0
- data/ext/{ext/klass → window}/window.h +3 -3
- data/lib/sfml/version.rb +4 -2
- data/lib/sfml.rb +2 -0
- metadata +163 -56
- data/ext/circle.c +0 -198
- data/ext/clock.c +0 -65
- data/ext/color.c +0 -43
- data/ext/event.c +0 -148
- data/ext/ext/klass/color.h +0 -26
- data/ext/ext/klass/drawable/image.h +0 -4
- data/ext/ext/klass/drawable/polygon.h +0 -4
- data/ext/ext/klass/drawable/rectangle.h +0 -4
- data/ext/ext/klass/drawable/sprite.h +0 -4
- data/ext/ext/klass/drawable/texture.h +0 -4
- data/ext/ext/klass/event/event_name.h +0 -8
- data/ext/ext/klass/event.h +0 -12
- data/ext/ext/klass/keyboard.h +0 -8
- data/ext/ext/klass/render_state.h +0 -16
- data/ext/ext/klass/target.h +0 -18
- data/ext/ext/klass/transform.h +0 -17
- data/ext/ext/klass/video_mode.h +0 -12
- data/ext/ext/module/drawable/drawable.h +0 -10
- data/ext/ext/module/transform.h +0 -18
- data/ext/ext/module.h +0 -10
- data/ext/ext/rect.h +0 -16
- data/ext/ext/style_name.h +0 -11
- data/ext/ext/vec2.h +0 -38
- data/ext/image.c +0 -5
- data/ext/polygon.c +0 -5
- data/ext/rect.c +0 -26
- data/ext/rectangle.c +0 -5
- data/ext/render_state.c +0 -109
- data/ext/sprite.c +0 -5
- data/ext/style_name.c +0 -15
- data/ext/target.c +0 -106
- data/ext/texture.c +0 -5
- data/ext/transform.c +0 -107
- data/ext/vec2.c +0 -42
- data/ext/video_mode.c +0 -78
- data/ext/window.c +0 -274
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#include "audio/sound_buffer.h"
|
|
2
|
+
|
|
3
|
+
#include <ruby.h>
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
|
|
8
|
+
#include "audio/audio_enums.h"
|
|
9
|
+
#include "core/exceptions.h"
|
|
10
|
+
#include "core/macros.h"
|
|
11
|
+
#include "system/input_stream.h"
|
|
12
|
+
#include "system/time.h"
|
|
13
|
+
|
|
14
|
+
typedef struct {
|
|
15
|
+
sfSoundBuffer *buffer;
|
|
16
|
+
bool owns;
|
|
17
|
+
} SoundBuffer;
|
|
18
|
+
|
|
19
|
+
static VALUE rb_cSoundBuffer;
|
|
20
|
+
|
|
21
|
+
static void SoundBuffer_free(void *ptr) {
|
|
22
|
+
SoundBuffer *sound_buffer = ptr;
|
|
23
|
+
|
|
24
|
+
if (sound_buffer->owns) {
|
|
25
|
+
sfSoundBuffer_destroy(sound_buffer->buffer);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
free(sound_buffer);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static const rb_data_type_t SoundBuffer_data_type = {
|
|
32
|
+
.wrap_struct_name = "SFML::SoundBuffer",
|
|
33
|
+
.function = {.dmark = NULL, .dfree = SoundBuffer_free, .dsize = NULL},
|
|
34
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
static VALUE SoundBuffer_wrap(VALUE klass, sfSoundBuffer *buffer) {
|
|
38
|
+
SoundBuffer *ptr;
|
|
39
|
+
|
|
40
|
+
if (buffer == NULL) {
|
|
41
|
+
rb_raise(rb_eRuntimeError, "failed to create sound buffer");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ptr = malloc(sizeof(SoundBuffer));
|
|
45
|
+
ptr->buffer = buffer;
|
|
46
|
+
ptr->owns = true;
|
|
47
|
+
|
|
48
|
+
return TypedData_Wrap_Struct(klass, &SoundBuffer_data_type, ptr);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
VALUE sound_buffer_from_borrowed(const sfSoundBuffer *buffer) {
|
|
52
|
+
SoundBuffer *ptr;
|
|
53
|
+
|
|
54
|
+
if (buffer == NULL) {
|
|
55
|
+
return Qnil;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ptr = malloc(sizeof(SoundBuffer));
|
|
59
|
+
ptr->buffer = (sfSoundBuffer *) buffer;
|
|
60
|
+
ptr->owns = false;
|
|
61
|
+
|
|
62
|
+
return TypedData_Wrap_Struct(rb_cSoundBuffer, &SoundBuffer_data_type, ptr);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static VALUE SoundBuffer_from_file(VALUE klass, VALUE rb_path) {
|
|
66
|
+
return SoundBuffer_wrap(klass, sfSoundBuffer_createFromFile(StringValueCStr(rb_path)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static VALUE SoundBuffer_from_memory(VALUE klass, VALUE rb_data) {
|
|
70
|
+
StringValue(rb_data);
|
|
71
|
+
|
|
72
|
+
return SoundBuffer_wrap(klass, sfSoundBuffer_createFromMemory(RSTRING_PTR(rb_data),
|
|
73
|
+
(size_t) RSTRING_LEN(rb_data)));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static VALUE SoundBuffer_from_stream(VALUE klass, VALUE rb_stream) {
|
|
77
|
+
VALUE holder = Qnil;
|
|
78
|
+
sfInputStream *stream = input_stream_from_rb(rb_stream, &holder);
|
|
79
|
+
|
|
80
|
+
(void) holder;
|
|
81
|
+
|
|
82
|
+
return SoundBuffer_wrap(klass, sfSoundBuffer_createFromStream(stream));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* SFML rejects a buffer whose channel map does not have exactly one entry per
|
|
86
|
+
channel, so an omitted map is filled with the conventional layout for 1 and
|
|
87
|
+
2 channels and left Unspecified beyond that. */
|
|
88
|
+
static void SoundBuffer_default_channel_map(unsigned int channel_count, sfSoundChannel *map) {
|
|
89
|
+
static const sfSoundChannel surround[] = {
|
|
90
|
+
sfSoundChannelFrontLeft, sfSoundChannelFrontRight, sfSoundChannelFrontCenter,
|
|
91
|
+
sfSoundChannelLowFrequencyEffects, sfSoundChannelBackLeft, sfSoundChannelBackRight,
|
|
92
|
+
sfSoundChannelSideLeft, sfSoundChannelSideRight, sfSoundChannelTopCenter
|
|
93
|
+
};
|
|
94
|
+
unsigned int i;
|
|
95
|
+
|
|
96
|
+
for (i = 0; i < channel_count; i++) {
|
|
97
|
+
if (i < sizeof(surround) / sizeof(surround[0])) {
|
|
98
|
+
map[i] = surround[i];
|
|
99
|
+
} else {
|
|
100
|
+
map[i] = sfSoundChannelUnspecified;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (channel_count == 1) {
|
|
105
|
+
map[0] = sfSoundChannelMono;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Copies the samples into a contiguous int16 buffer: an Array is converted
|
|
110
|
+
element by element, a String is memcpy'd out of (possibly unaligned) Ruby
|
|
111
|
+
storage. The channel map, when given, is translated symbol by symbol. */
|
|
112
|
+
static VALUE SoundBuffer_from_samples(int argc, VALUE *argv, VALUE klass) {
|
|
113
|
+
VALUE rb_samples, rb_channel_count, rb_sample_rate, rb_channel_map;
|
|
114
|
+
int16_t *samples;
|
|
115
|
+
sfSoundChannel *channel_map;
|
|
116
|
+
unsigned int channel_count;
|
|
117
|
+
uint64_t sample_count;
|
|
118
|
+
sfSoundBuffer *buffer;
|
|
119
|
+
|
|
120
|
+
rb_scan_args(argc, argv, "31", &rb_samples, &rb_channel_count, &rb_sample_rate,
|
|
121
|
+
&rb_channel_map);
|
|
122
|
+
|
|
123
|
+
channel_count = (unsigned int) NUM2INT(rb_channel_count);
|
|
124
|
+
|
|
125
|
+
if (channel_count == 0) {
|
|
126
|
+
rb_raise(rb_eArgError, "channel count must be positive");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (RB_TYPE_P(rb_samples, T_STRING)) {
|
|
130
|
+
size_t bytes = (size_t) RSTRING_LEN(rb_samples);
|
|
131
|
+
|
|
132
|
+
if (bytes % sizeof(int16_t) != 0) {
|
|
133
|
+
rb_raise(rb_eArgError, "sample string length must be a multiple of 2 bytes");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
sample_count = bytes / sizeof(int16_t);
|
|
137
|
+
samples = malloc(bytes > 0 ? bytes : 1);
|
|
138
|
+
|
|
139
|
+
if (bytes > 0) {
|
|
140
|
+
memcpy(samples, RSTRING_PTR(rb_samples), bytes);
|
|
141
|
+
}
|
|
142
|
+
} else if (RB_TYPE_P(rb_samples, T_ARRAY)) {
|
|
143
|
+
long i;
|
|
144
|
+
|
|
145
|
+
sample_count = (uint64_t) RARRAY_LEN(rb_samples);
|
|
146
|
+
samples = malloc(sizeof(int16_t) * ((size_t) sample_count + 1));
|
|
147
|
+
|
|
148
|
+
for (i = 0; i < (long) sample_count; i++) {
|
|
149
|
+
samples[i] = (int16_t) NUM2INT(rb_ary_entry(rb_samples, i));
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
rb_raise(rb_eArgError, "samples must be an Array of integers or a String");
|
|
153
|
+
return Qnil;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
channel_map = malloc(sizeof(sfSoundChannel) * channel_count);
|
|
157
|
+
|
|
158
|
+
if (NIL_P(rb_channel_map)) {
|
|
159
|
+
SoundBuffer_default_channel_map(channel_count, channel_map);
|
|
160
|
+
} else {
|
|
161
|
+
long i;
|
|
162
|
+
|
|
163
|
+
if (!RB_TYPE_P(rb_channel_map, T_ARRAY) ||
|
|
164
|
+
(unsigned long) RARRAY_LEN(rb_channel_map) != channel_count) {
|
|
165
|
+
free(samples);
|
|
166
|
+
free(channel_map);
|
|
167
|
+
rb_raise(rb_eArgError, "channel map must have exactly one entry per channel");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (i = 0; i < (long) channel_count; i++) {
|
|
171
|
+
channel_map[i] = sound_channel_from_rb(rb_ary_entry(rb_channel_map, i));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
buffer = sfSoundBuffer_createFromSamples(samples, sample_count, channel_count,
|
|
176
|
+
(unsigned int) NUM2INT(rb_sample_rate), channel_map,
|
|
177
|
+
channel_count);
|
|
178
|
+
|
|
179
|
+
free(samples);
|
|
180
|
+
free(channel_map);
|
|
181
|
+
|
|
182
|
+
return SoundBuffer_wrap(klass, buffer);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static VALUE SoundBuffer_copy(VALUE self) {
|
|
186
|
+
return SoundBuffer_wrap(Get_Klass_SoundBuffer(),
|
|
187
|
+
sfSoundBuffer_copy(Get_SoundBuffer_Struct(self)));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static VALUE SoundBuffer_save_to_file(VALUE self, VALUE rb_path) {
|
|
191
|
+
return BOOL2RB(sfSoundBuffer_saveToFile(Get_SoundBuffer_Struct(self), StringValueCStr(rb_path)));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static VALUE SoundBuffer_samples(VALUE self) {
|
|
195
|
+
const int16_t *samples = sfSoundBuffer_getSamples(Get_SoundBuffer_Struct(self));
|
|
196
|
+
uint64_t count = sfSoundBuffer_getSampleCount(Get_SoundBuffer_Struct(self));
|
|
197
|
+
VALUE rb_array;
|
|
198
|
+
uint64_t i;
|
|
199
|
+
|
|
200
|
+
if (samples == NULL) {
|
|
201
|
+
return rb_ary_new();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
rb_array = rb_ary_new_capa((long) count);
|
|
205
|
+
|
|
206
|
+
for (i = 0; i < count; i++) {
|
|
207
|
+
rb_ary_push(rb_array, INT2NUM(samples[i]));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return rb_array;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static VALUE SoundBuffer_sample_count(VALUE self) {
|
|
214
|
+
return ULL2NUM(sfSoundBuffer_getSampleCount(Get_SoundBuffer_Struct(self)));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
static VALUE SoundBuffer_sample_rate(VALUE self) {
|
|
218
|
+
return UINT2NUM(sfSoundBuffer_getSampleRate(Get_SoundBuffer_Struct(self)));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static VALUE SoundBuffer_channel_count(VALUE self) {
|
|
222
|
+
return UINT2NUM(sfSoundBuffer_getChannelCount(Get_SoundBuffer_Struct(self)));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
static VALUE SoundBuffer_channel_map(VALUE self) {
|
|
226
|
+
size_t count = 0;
|
|
227
|
+
sfSoundChannel *map = sfSoundBuffer_getChannelMap(Get_SoundBuffer_Struct(self), &count);
|
|
228
|
+
VALUE rb_array;
|
|
229
|
+
size_t i;
|
|
230
|
+
|
|
231
|
+
if (map == NULL) {
|
|
232
|
+
return rb_ary_new();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
rb_array = rb_ary_new_capa((long) count);
|
|
236
|
+
|
|
237
|
+
for (i = 0; i < count; i++) {
|
|
238
|
+
rb_ary_push(rb_array, ID2SYM(rb_intern(sound_channel_name(map[i]))));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return rb_array;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static VALUE SoundBuffer_duration(VALUE self) {
|
|
245
|
+
return time_to_rb(sfSoundBuffer_getDuration(Get_SoundBuffer_Struct(self)));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void Init_SoundBuffer(VALUE rb_module) {
|
|
249
|
+
rb_cSoundBuffer = rb_define_class_under(rb_module, "SoundBuffer", rb_cObject);
|
|
250
|
+
|
|
251
|
+
rb_define_singleton_method(rb_cSoundBuffer, "from_file", SoundBuffer_from_file, 1);
|
|
252
|
+
rb_define_singleton_method(rb_cSoundBuffer, "from_memory", SoundBuffer_from_memory, 1);
|
|
253
|
+
rb_define_singleton_method(rb_cSoundBuffer, "from_stream", SoundBuffer_from_stream, 1);
|
|
254
|
+
rb_define_singleton_method(rb_cSoundBuffer, "from_samples", SoundBuffer_from_samples, -1);
|
|
255
|
+
|
|
256
|
+
rb_define_method(rb_cSoundBuffer, "copy", SoundBuffer_copy, 0);
|
|
257
|
+
rb_define_method(rb_cSoundBuffer, "save_to_file", SoundBuffer_save_to_file, 1);
|
|
258
|
+
rb_define_method(rb_cSoundBuffer, "samples", SoundBuffer_samples, 0);
|
|
259
|
+
rb_define_method(rb_cSoundBuffer, "sample_count", SoundBuffer_sample_count, 0);
|
|
260
|
+
rb_define_method(rb_cSoundBuffer, "sample_rate", SoundBuffer_sample_rate, 0);
|
|
261
|
+
rb_define_method(rb_cSoundBuffer, "channel_count", SoundBuffer_channel_count, 0);
|
|
262
|
+
rb_define_method(rb_cSoundBuffer, "channel_map", SoundBuffer_channel_map, 0);
|
|
263
|
+
rb_define_method(rb_cSoundBuffer, "duration", SoundBuffer_duration, 0);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
VALUE Get_Klass_SoundBuffer(void) {
|
|
267
|
+
return rb_cSoundBuffer;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
void *Get_SoundBuffer_Struct(VALUE self) {
|
|
271
|
+
SoundBuffer *ptr;
|
|
272
|
+
TypedData_Get_Struct(self, SoundBuffer, &SoundBuffer_data_type, ptr);
|
|
273
|
+
return ptr->buffer;
|
|
274
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#ifndef SFML_RB_AUDIO_SOUND_BUFFER_H
|
|
2
|
+
#define SFML_RB_AUDIO_SOUND_BUFFER_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
|
|
6
|
+
#include "core/sfml.h"
|
|
7
|
+
|
|
8
|
+
void Init_SoundBuffer(VALUE rb_module);
|
|
9
|
+
|
|
10
|
+
VALUE Get_Klass_SoundBuffer(void);
|
|
11
|
+
|
|
12
|
+
void *Get_SoundBuffer_Struct(VALUE self);
|
|
13
|
+
|
|
14
|
+
/* Wraps a buffer owned by someone else (a SoundBufferRecorder) without taking
|
|
15
|
+
ownership, so freeing the wrapper must not destroy it. */
|
|
16
|
+
VALUE sound_buffer_from_borrowed(const sfSoundBuffer *buffer);
|
|
17
|
+
|
|
18
|
+
#endif //SFML_RB_AUDIO_SOUND_BUFFER_H
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#include "audio/sound_buffer_recorder.h"
|
|
2
|
+
|
|
3
|
+
#include <ruby.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
|
|
6
|
+
#include "audio/audio_enums.h"
|
|
7
|
+
#include "audio/sound_buffer.h"
|
|
8
|
+
#include "core/macros.h"
|
|
9
|
+
|
|
10
|
+
typedef struct {
|
|
11
|
+
sfSoundBufferRecorder *handle;
|
|
12
|
+
} SoundBufferRecorder;
|
|
13
|
+
|
|
14
|
+
static VALUE rb_cSoundBufferRecorder;
|
|
15
|
+
|
|
16
|
+
static void SoundBufferRecorder_free(void *ptr) {
|
|
17
|
+
SoundBufferRecorder *recorder = ptr;
|
|
18
|
+
|
|
19
|
+
if (recorder->handle != NULL) {
|
|
20
|
+
sfSoundBufferRecorder_destroy(recorder->handle);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
free(recorder);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static const rb_data_type_t SoundBufferRecorder_data_type = {
|
|
27
|
+
.wrap_struct_name = "SFML::SoundBufferRecorder",
|
|
28
|
+
.function = {.dmark = NULL, .dfree = SoundBufferRecorder_free, .dsize = NULL},
|
|
29
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static VALUE SoundBufferRecorder_wrap(VALUE klass, sfSoundBufferRecorder *handle) {
|
|
33
|
+
SoundBufferRecorder *ptr;
|
|
34
|
+
|
|
35
|
+
if (handle == NULL) {
|
|
36
|
+
rb_raise(rb_eRuntimeError, "failed to create sound buffer recorder (no capture device?)");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
ptr = malloc(sizeof(SoundBufferRecorder));
|
|
40
|
+
ptr->handle = handle;
|
|
41
|
+
|
|
42
|
+
return TypedData_Wrap_Struct(klass, &SoundBufferRecorder_data_type, ptr);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static VALUE SoundBufferRecorder_new(VALUE klass) {
|
|
46
|
+
return SoundBufferRecorder_wrap(klass, sfSoundBufferRecorder_create());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static VALUE SoundBufferRecorder_start(VALUE self, VALUE rb_sample_rate) {
|
|
50
|
+
return BOOL2RB(sfSoundBufferRecorder_start(Get_SoundBufferRecorder_Struct(self),
|
|
51
|
+
(unsigned int) NUM2INT(rb_sample_rate)));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static VALUE SoundBufferRecorder_stop(VALUE self) {
|
|
55
|
+
sfSoundBufferRecorder_stop(Get_SoundBufferRecorder_Struct(self));
|
|
56
|
+
return self;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static VALUE SoundBufferRecorder_sample_rate(VALUE self) {
|
|
60
|
+
return UINT2NUM(sfSoundBufferRecorder_getSampleRate(Get_SoundBufferRecorder_Struct(self)));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static VALUE SoundBufferRecorder_buffer(VALUE self) {
|
|
64
|
+
return sound_buffer_from_borrowed(sfSoundBufferRecorder_getBuffer(Get_SoundBufferRecorder_Struct(self)));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static VALUE SoundBufferRecorder_device(VALUE self) {
|
|
68
|
+
return rb_str_new_cstr(sfSoundBufferRecorder_getDevice(Get_SoundBufferRecorder_Struct(self)));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static VALUE SoundBufferRecorder_set_device(VALUE self, VALUE rb_name) {
|
|
72
|
+
return BOOL2RB(sfSoundBufferRecorder_setDevice(Get_SoundBufferRecorder_Struct(self),
|
|
73
|
+
StringValueCStr(rb_name)));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static VALUE SoundBufferRecorder_channel_count(VALUE self) {
|
|
77
|
+
return UINT2NUM(sfSoundBufferRecorder_getChannelCount(Get_SoundBufferRecorder_Struct(self)));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static VALUE SoundBufferRecorder_set_channel_count(VALUE self, VALUE rb_count) {
|
|
81
|
+
sfSoundBufferRecorder_setChannelCount(Get_SoundBufferRecorder_Struct(self),
|
|
82
|
+
(unsigned int) NUM2INT(rb_count));
|
|
83
|
+
return rb_count;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void Init_SoundBufferRecorder(VALUE rb_module) {
|
|
87
|
+
rb_cSoundBufferRecorder = rb_define_class_under(rb_module, "SoundBufferRecorder", rb_cObject);
|
|
88
|
+
|
|
89
|
+
rb_define_singleton_method(rb_cSoundBufferRecorder, "new", SoundBufferRecorder_new, 0);
|
|
90
|
+
|
|
91
|
+
rb_define_method(rb_cSoundBufferRecorder, "start", SoundBufferRecorder_start, 1);
|
|
92
|
+
rb_define_method(rb_cSoundBufferRecorder, "stop", SoundBufferRecorder_stop, 0);
|
|
93
|
+
rb_define_method(rb_cSoundBufferRecorder, "sample_rate", SoundBufferRecorder_sample_rate, 0);
|
|
94
|
+
rb_define_method(rb_cSoundBufferRecorder, "buffer", SoundBufferRecorder_buffer, 0);
|
|
95
|
+
rb_define_method(rb_cSoundBufferRecorder, "device", SoundBufferRecorder_device, 0);
|
|
96
|
+
rb_define_method(rb_cSoundBufferRecorder, "device=", SoundBufferRecorder_set_device, 1);
|
|
97
|
+
rb_define_method(rb_cSoundBufferRecorder, "channel_count", SoundBufferRecorder_channel_count, 0);
|
|
98
|
+
rb_define_method(rb_cSoundBufferRecorder, "channel_count=", SoundBufferRecorder_set_channel_count, 1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
VALUE Get_Klass_SoundBufferRecorder(void) {
|
|
102
|
+
return rb_cSoundBufferRecorder;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
void *Get_SoundBufferRecorder_Struct(VALUE self) {
|
|
106
|
+
SoundBufferRecorder *ptr;
|
|
107
|
+
TypedData_Get_Struct(self, SoundBufferRecorder, &SoundBufferRecorder_data_type, ptr);
|
|
108
|
+
return ptr->handle;
|
|
109
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#ifndef SFML_RB_AUDIO_SOUND_BUFFER_RECORDER_H
|
|
2
|
+
#define SFML_RB_AUDIO_SOUND_BUFFER_RECORDER_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
|
|
6
|
+
#include "core/sfml.h"
|
|
7
|
+
|
|
8
|
+
void Init_SoundBufferRecorder(VALUE rb_module);
|
|
9
|
+
|
|
10
|
+
VALUE Get_Klass_SoundBufferRecorder(void);
|
|
11
|
+
|
|
12
|
+
void *Get_SoundBufferRecorder_Struct(VALUE self);
|
|
13
|
+
|
|
14
|
+
#endif //SFML_RB_AUDIO_SOUND_BUFFER_RECORDER_H
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#include "audio/sound_recorder.h"
|
|
2
|
+
|
|
3
|
+
#include <ruby.h>
|
|
4
|
+
#include <ruby/thread.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
|
|
8
|
+
#include "audio/audio_enums.h"
|
|
9
|
+
#include "core/macros.h"
|
|
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. */
|
|
16
|
+
typedef struct {
|
|
17
|
+
VALUE rb_self;
|
|
18
|
+
sfSoundRecorder *handle;
|
|
19
|
+
} SoundRecorder;
|
|
20
|
+
|
|
21
|
+
static VALUE rb_cSoundRecorder;
|
|
22
|
+
|
|
23
|
+
static void SoundRecorder_mark(void *ptr) {
|
|
24
|
+
SoundRecorder *recorder = ptr;
|
|
25
|
+
|
|
26
|
+
rb_gc_mark(recorder->rb_self);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static void SoundRecorder_free(void *ptr) {
|
|
30
|
+
SoundRecorder *recorder = ptr;
|
|
31
|
+
|
|
32
|
+
if (recorder->handle != NULL) {
|
|
33
|
+
sfSoundRecorder_destroy(recorder->handle);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
free(recorder);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static const rb_data_type_t SoundRecorder_data_type = {
|
|
40
|
+
.wrap_struct_name = "SFML::SoundRecorder",
|
|
41
|
+
.function = {.dmark = SoundRecorder_mark, .dfree = SoundRecorder_free, .dsize = NULL},
|
|
42
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
typedef struct {
|
|
46
|
+
VALUE self;
|
|
47
|
+
ID method;
|
|
48
|
+
} InvokeContext;
|
|
49
|
+
|
|
50
|
+
static VALUE SoundRecorder_invoke_body(VALUE raw) {
|
|
51
|
+
InvokeContext *ctx = (InvokeContext *) raw;
|
|
52
|
+
|
|
53
|
+
return rb_funcall(ctx->self, ctx->method, 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
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};
|
|
59
|
+
int state = 0;
|
|
60
|
+
|
|
61
|
+
rb_protect(SoundRecorder_invoke_body, (VALUE) &ctx, &state);
|
|
62
|
+
|
|
63
|
+
if (state) {
|
|
64
|
+
rb_set_errinfo(Qnil);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static bool SoundRecorder_on_start(void *userData) {
|
|
69
|
+
SoundRecorder *recorder = userData;
|
|
70
|
+
|
|
71
|
+
if (rb_respond_to(recorder->rb_self, rb_intern("on_start"))) {
|
|
72
|
+
SoundRecorder_invoke(recorder->rb_self, rb_intern("on_start"));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
typedef struct {
|
|
79
|
+
SoundRecorder *recorder;
|
|
80
|
+
const int16_t *samples;
|
|
81
|
+
size_t sample_count;
|
|
82
|
+
int ok;
|
|
83
|
+
} ProcessContext;
|
|
84
|
+
|
|
85
|
+
static VALUE SoundRecorder_process_body(VALUE raw) {
|
|
86
|
+
ProcessContext *ctx = (ProcessContext *) raw;
|
|
87
|
+
VALUE rb_samples = rb_ary_new_capa((long) ctx->sample_count);
|
|
88
|
+
VALUE result;
|
|
89
|
+
size_t i;
|
|
90
|
+
|
|
91
|
+
for (i = 0; i < ctx->sample_count; i++) {
|
|
92
|
+
rb_ary_push(rb_samples, INT2NUM(ctx->samples[i]));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
result = rb_funcall(ctx->recorder->rb_self, rb_intern("on_process"), 1, rb_samples);
|
|
96
|
+
ctx->ok = RTEST(result) ? 1 : 0;
|
|
97
|
+
|
|
98
|
+
return Qnil;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static void *SoundRecorder_process_gvl(void *raw) {
|
|
102
|
+
int state = 0;
|
|
103
|
+
|
|
104
|
+
rb_protect(SoundRecorder_process_body, (VALUE) raw, &state);
|
|
105
|
+
|
|
106
|
+
if (state) {
|
|
107
|
+
rb_set_errinfo(Qnil);
|
|
108
|
+
((ProcessContext *) raw)->ok = 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return NULL;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static bool SoundRecorder_on_process(const int16_t *samples, size_t sample_count, void *userData) {
|
|
115
|
+
SoundRecorder *recorder = userData;
|
|
116
|
+
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);
|
|
121
|
+
|
|
122
|
+
return ctx.ok ? true : false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static void SoundRecorder_on_stop(void *userData) {
|
|
126
|
+
SoundRecorder *recorder = userData;
|
|
127
|
+
|
|
128
|
+
if (rb_respond_to(recorder->rb_self, rb_intern("on_stop"))) {
|
|
129
|
+
SoundRecorder_invoke(recorder->rb_self, rb_intern("on_stop"));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static VALUE SoundRecorder_new(VALUE klass) {
|
|
134
|
+
SoundRecorder *ptr;
|
|
135
|
+
sfSoundRecorder *handle;
|
|
136
|
+
VALUE self;
|
|
137
|
+
|
|
138
|
+
ptr = malloc(sizeof(SoundRecorder));
|
|
139
|
+
ptr->rb_self = Qnil;
|
|
140
|
+
ptr->handle = NULL;
|
|
141
|
+
|
|
142
|
+
self = TypedData_Wrap_Struct(klass, &SoundRecorder_data_type, ptr);
|
|
143
|
+
ptr->rb_self = self;
|
|
144
|
+
|
|
145
|
+
if (!rb_respond_to(self, rb_intern("on_process"))) {
|
|
146
|
+
/* Ruby already owns the wrapper; SoundRecorder_free handles the NULL
|
|
147
|
+
handle, so let GC clean up after the raise. */
|
|
148
|
+
rb_raise(rb_eNotImpError, "subclass must define #on_process");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
handle = sfSoundRecorder_create(SoundRecorder_on_start, SoundRecorder_on_process,
|
|
152
|
+
SoundRecorder_on_stop, ptr);
|
|
153
|
+
|
|
154
|
+
if (handle == NULL) {
|
|
155
|
+
rb_raise(rb_eRuntimeError, "failed to create sound recorder (no capture device?)");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
ptr->handle = handle;
|
|
159
|
+
|
|
160
|
+
return self;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static VALUE SoundRecorder_start(VALUE self, VALUE rb_sample_rate) {
|
|
164
|
+
return BOOL2RB(sfSoundRecorder_start(Get_SoundRecorder_Struct(self),
|
|
165
|
+
(unsigned int) NUM2INT(rb_sample_rate)));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static VALUE SoundRecorder_stop(VALUE self) {
|
|
169
|
+
sfSoundRecorder_stop(Get_SoundRecorder_Struct(self));
|
|
170
|
+
return self;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static VALUE SoundRecorder_sample_rate(VALUE self) {
|
|
174
|
+
return UINT2NUM(sfSoundRecorder_getSampleRate(Get_SoundRecorder_Struct(self)));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static VALUE SoundRecorder_available(VALUE klass) {
|
|
178
|
+
return BOOL2RB(sfSoundRecorder_isAvailable());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static VALUE SoundRecorder_available_devices(VALUE klass) {
|
|
182
|
+
size_t count = 0;
|
|
183
|
+
const char *const *devices = sfSoundRecorder_getAvailableDevices(&count);
|
|
184
|
+
VALUE rb_array;
|
|
185
|
+
size_t i;
|
|
186
|
+
|
|
187
|
+
if (devices == NULL) {
|
|
188
|
+
return rb_ary_new();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
rb_array = rb_ary_new_capa((long) count);
|
|
192
|
+
|
|
193
|
+
for (i = 0; i < count; i++) {
|
|
194
|
+
rb_ary_push(rb_array, rb_str_new_cstr(devices[i]));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return rb_array;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
static VALUE SoundRecorder_default_device(VALUE klass) {
|
|
201
|
+
return rb_str_new_cstr(sfSoundRecorder_getDefaultDevice());
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
static VALUE SoundRecorder_device(VALUE self) {
|
|
205
|
+
return rb_str_new_cstr(sfSoundRecorder_getDevice(Get_SoundRecorder_Struct(self)));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static VALUE SoundRecorder_set_device(VALUE self, VALUE rb_name) {
|
|
209
|
+
return BOOL2RB(
|
|
210
|
+
sfSoundRecorder_setDevice(Get_SoundRecorder_Struct(self), StringValueCStr(rb_name)));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static VALUE SoundRecorder_channel_count(VALUE self) {
|
|
214
|
+
return UINT2NUM(sfSoundRecorder_getChannelCount(Get_SoundRecorder_Struct(self)));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
static VALUE SoundRecorder_set_channel_count(VALUE self, VALUE rb_count) {
|
|
218
|
+
sfSoundRecorder_setChannelCount(Get_SoundRecorder_Struct(self), (unsigned int) NUM2INT(rb_count));
|
|
219
|
+
return rb_count;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static VALUE SoundRecorder_channel_map(VALUE self) {
|
|
223
|
+
size_t count = 0;
|
|
224
|
+
sfSoundChannel *map = sfSoundRecorder_getChannelMap(Get_SoundRecorder_Struct(self), &count);
|
|
225
|
+
VALUE rb_array;
|
|
226
|
+
size_t i;
|
|
227
|
+
|
|
228
|
+
if (map == NULL) {
|
|
229
|
+
return rb_ary_new();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
rb_array = rb_ary_new_capa((long) count);
|
|
233
|
+
|
|
234
|
+
for (i = 0; i < count; i++) {
|
|
235
|
+
rb_ary_push(rb_array, ID2SYM(rb_intern(sound_channel_name(map[i]))));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return rb_array;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
void Init_SoundRecorder(VALUE rb_module) {
|
|
242
|
+
rb_cSoundRecorder = rb_define_class_under(rb_module, "SoundRecorder", rb_cObject);
|
|
243
|
+
|
|
244
|
+
rb_define_singleton_method(rb_cSoundRecorder, "new", SoundRecorder_new, 0);
|
|
245
|
+
rb_define_singleton_method(rb_cSoundRecorder, "available?", SoundRecorder_available, 0);
|
|
246
|
+
rb_define_singleton_method(rb_cSoundRecorder, "available_devices",
|
|
247
|
+
SoundRecorder_available_devices, 0);
|
|
248
|
+
rb_define_singleton_method(rb_cSoundRecorder, "default_device", SoundRecorder_default_device, 0);
|
|
249
|
+
|
|
250
|
+
rb_define_method(rb_cSoundRecorder, "start", SoundRecorder_start, 1);
|
|
251
|
+
rb_define_method(rb_cSoundRecorder, "stop", SoundRecorder_stop, 0);
|
|
252
|
+
rb_define_method(rb_cSoundRecorder, "sample_rate", SoundRecorder_sample_rate, 0);
|
|
253
|
+
rb_define_method(rb_cSoundRecorder, "device", SoundRecorder_device, 0);
|
|
254
|
+
rb_define_method(rb_cSoundRecorder, "device=", SoundRecorder_set_device, 1);
|
|
255
|
+
rb_define_method(rb_cSoundRecorder, "channel_count", SoundRecorder_channel_count, 0);
|
|
256
|
+
rb_define_method(rb_cSoundRecorder, "channel_count=", SoundRecorder_set_channel_count, 1);
|
|
257
|
+
rb_define_method(rb_cSoundRecorder, "channel_map", SoundRecorder_channel_map, 0);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
VALUE Get_Klass_SoundRecorder(void) {
|
|
261
|
+
return rb_cSoundRecorder;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
void *Get_SoundRecorder_Struct(VALUE self) {
|
|
265
|
+
SoundRecorder *ptr;
|
|
266
|
+
TypedData_Get_Struct(self, SoundRecorder, &SoundRecorder_data_type, ptr);
|
|
267
|
+
return ptr->handle;
|
|
268
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#ifndef SFML_RB_AUDIO_SOUND_RECORDER_H
|
|
2
|
+
#define SFML_RB_AUDIO_SOUND_RECORDER_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
|
|
6
|
+
#include "core/sfml.h"
|
|
7
|
+
|
|
8
|
+
void Init_SoundRecorder(VALUE rb_module);
|
|
9
|
+
|
|
10
|
+
VALUE Get_Klass_SoundRecorder(void);
|
|
11
|
+
|
|
12
|
+
void *Get_SoundRecorder_Struct(VALUE self);
|
|
13
|
+
|
|
14
|
+
#endif //SFML_RB_AUDIO_SOUND_RECORDER_H
|