ruby-sfml 3.0.0.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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +101 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +245 -0
  5. data/ext/ruby-sfml/extconf.rb +69 -0
  6. data/lib/sfml/assets/fonts/DejaVuSans.LICENSE.txt +78 -0
  7. data/lib/sfml/assets/fonts/DejaVuSans.ttf +0 -0
  8. data/lib/sfml/assets.rb +121 -0
  9. data/lib/sfml/audio/listener.rb +55 -0
  10. data/lib/sfml/audio/music.rb +88 -0
  11. data/lib/sfml/audio/sound.rb +102 -0
  12. data/lib/sfml/audio/sound_buffer.rb +38 -0
  13. data/lib/sfml/audio/sound_buffer_recorder.rb +71 -0
  14. data/lib/sfml/audio/sound_recorder.rb +30 -0
  15. data/lib/sfml/c/audio.rb +106 -0
  16. data/lib/sfml/c/graphics.rb +425 -0
  17. data/lib/sfml/c/network.rb +79 -0
  18. data/lib/sfml/c/system.rb +43 -0
  19. data/lib/sfml/c/window.rb +186 -0
  20. data/lib/sfml/c.rb +72 -0
  21. data/lib/sfml/game.rb +101 -0
  22. data/lib/sfml/graphics/blend_mode.rb +108 -0
  23. data/lib/sfml/graphics/circle_shape.rb +67 -0
  24. data/lib/sfml/graphics/color.rb +89 -0
  25. data/lib/sfml/graphics/convex_shape.rb +82 -0
  26. data/lib/sfml/graphics/font.rb +67 -0
  27. data/lib/sfml/graphics/image.rb +125 -0
  28. data/lib/sfml/graphics/rectangle_shape.rb +62 -0
  29. data/lib/sfml/graphics/render_states.rb +56 -0
  30. data/lib/sfml/graphics/render_target.rb +146 -0
  31. data/lib/sfml/graphics/render_texture.rb +72 -0
  32. data/lib/sfml/graphics/render_window.rb +154 -0
  33. data/lib/sfml/graphics/shader.rb +132 -0
  34. data/lib/sfml/graphics/sprite.rb +75 -0
  35. data/lib/sfml/graphics/text.rb +144 -0
  36. data/lib/sfml/graphics/texture.rb +79 -0
  37. data/lib/sfml/graphics/transform.rb +150 -0
  38. data/lib/sfml/graphics/transformable.rb +74 -0
  39. data/lib/sfml/graphics/vertex.rb +53 -0
  40. data/lib/sfml/graphics/vertex_array.rb +114 -0
  41. data/lib/sfml/graphics/view.rb +126 -0
  42. data/lib/sfml/network/ip_address.rb +67 -0
  43. data/lib/sfml/network/tcp_listener.rb +61 -0
  44. data/lib/sfml/network/tcp_socket.rb +74 -0
  45. data/lib/sfml/network/udp_socket.rb +71 -0
  46. data/lib/sfml/system/clock.rb +44 -0
  47. data/lib/sfml/system/rect.rb +64 -0
  48. data/lib/sfml/system/time.rb +48 -0
  49. data/lib/sfml/system/vector2.rb +66 -0
  50. data/lib/sfml/system/vector3.rb +63 -0
  51. data/lib/sfml/version.rb +19 -0
  52. data/lib/sfml/window/clipboard.rb +38 -0
  53. data/lib/sfml/window/cursor.rb +68 -0
  54. data/lib/sfml/window/event.rb +133 -0
  55. data/lib/sfml/window/joystick.rb +90 -0
  56. data/lib/sfml/window/keyboard.rb +60 -0
  57. data/lib/sfml/window/mouse.rb +71 -0
  58. data/lib/sfml/window/video_mode.rb +37 -0
  59. data/lib/sfml/window/window.rb +149 -0
  60. data/lib/sfml.rb +98 -0
  61. data/ruby-sfml.gemspec +38 -0
  62. metadata +163 -0
@@ -0,0 +1,55 @@
1
+ module SFML
2
+ # The "ear" — a global, single-instance object that defines from
3
+ # where the player hears the world. Sounds positioned via Sound#position=
4
+ # attenuate based on their distance from this point.
5
+ #
6
+ # SFML::Listener.position = [400, 300, 0] # follow your camera
7
+ # SFML::Listener.global_volume = 80 # 0..100, master gain
8
+ #
9
+ # For 2D games keep z = 0 and treat x, y as world coords. For
10
+ # first-person stuff also set Listener.direction to point along the
11
+ # camera forward.
12
+ module Listener
13
+ module_function
14
+
15
+ # Master volume in the range [0, 100]. Affects all sounds, music, etc.
16
+ def global_volume
17
+ C::Audio.sfListener_getGlobalVolume
18
+ end
19
+
20
+ def global_volume=(value)
21
+ C::Audio.sfListener_setGlobalVolume(value.to_f)
22
+ end
23
+
24
+ def position
25
+ Vector3.from_native(C::Audio.sfListener_getPosition)
26
+ end
27
+
28
+ def position=(value)
29
+ vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
30
+ C::Audio.sfListener_setPosition(vec.to_native_f)
31
+ end
32
+
33
+ # The forward direction of the listener (unit-length, doesn't have to be).
34
+ # Default: (0, 0, -1) — looking into the screen.
35
+ def direction
36
+ Vector3.from_native(C::Audio.sfListener_getDirection)
37
+ end
38
+
39
+ def direction=(value)
40
+ vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
41
+ C::Audio.sfListener_setDirection(vec.to_native_f)
42
+ end
43
+
44
+ # The "up" direction. Default: (0, 1, 0). Together with `direction`
45
+ # it determines listener orientation for stereo panning.
46
+ def up_vector
47
+ Vector3.from_native(C::Audio.sfListener_getUpVector)
48
+ end
49
+
50
+ def up_vector=(value)
51
+ vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
52
+ C::Audio.sfListener_setUpVector(vec.to_native_f)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,88 @@
1
+ module SFML
2
+ # A streamed audio source. Use this for long tracks (background music) so
3
+ # the file isn't loaded into memory all at once.
4
+ #
5
+ # bgm = SFML::Music.load("assets/track.ogg", looping: true, volume: 60)
6
+ # bgm.play
7
+ class Music
8
+ def self.load(path, **opts)
9
+ ptr = C::Audio.sfMusic_createFromFile(path.to_s)
10
+ raise Error, "Could not load music from #{path.inspect}" if ptr.null?
11
+
12
+ m = allocate
13
+ m.send(:_take_ownership, ptr)
14
+ m.instance_variable_set(:@looping, false)
15
+ m.volume = opts[:volume] if opts.key?(:volume)
16
+ m.pitch = opts[:pitch] if opts.key?(:pitch)
17
+ m.looping = opts[:looping] if opts.key?(:looping)
18
+ m
19
+ end
20
+
21
+ def play = C::Audio.sfMusic_play(@handle)
22
+ def pause = C::Audio.sfMusic_pause(@handle)
23
+ def stop = C::Audio.sfMusic_stop(@handle)
24
+
25
+ def status = C::Audio::STATUSES[C::Audio.sfMusic_getStatus(@handle)]
26
+ def playing? = status == :playing
27
+ def paused? = status == :paused
28
+ def stopped? = status == :stopped
29
+
30
+ def duration = Time.from_native(C::Audio.sfMusic_getDuration(@handle))
31
+
32
+ # Cached on the Ruby side; see Sound#looping? for the why.
33
+ def looping?
34
+ @looping
35
+ end
36
+
37
+ def looping=(value)
38
+ @looping = value ? true : false
39
+ C::Audio.sfMusic_setLooping(@handle, @looping)
40
+ end
41
+
42
+ def volume = C::Audio.sfMusic_getVolume(@handle)
43
+
44
+ def volume=(value)
45
+ C::Audio.sfMusic_setVolume(@handle, value.to_f)
46
+ end
47
+
48
+ def pitch = C::Audio.sfMusic_getPitch(@handle)
49
+
50
+ def pitch=(value)
51
+ C::Audio.sfMusic_setPitch(@handle, value.to_f)
52
+ end
53
+
54
+ # 3D positional audio — see SFML::Sound for the why.
55
+ def position
56
+ Vector3.from_native(C::Audio.sfMusic_getPosition(@handle))
57
+ end
58
+
59
+ def position=(value)
60
+ vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
61
+ C::Audio.sfMusic_setPosition(@handle, vec.to_native_f)
62
+ end
63
+
64
+ def attenuation = C::Audio.sfMusic_getAttenuation(@handle)
65
+
66
+ def attenuation=(value)
67
+ C::Audio.sfMusic_setAttenuation(@handle, value.to_f)
68
+ end
69
+
70
+ def min_distance = C::Audio.sfMusic_getMinDistance(@handle)
71
+
72
+ def min_distance=(value)
73
+ C::Audio.sfMusic_setMinDistance(@handle, value.to_f)
74
+ end
75
+
76
+ def relative_to_listener? = C::Audio.sfMusic_isRelativeToListener(@handle)
77
+
78
+ def relative_to_listener=(value)
79
+ C::Audio.sfMusic_setRelativeToListener(@handle, value ? true : false)
80
+ end
81
+
82
+ private
83
+
84
+ def _take_ownership(ptr)
85
+ @handle = FFI::AutoPointer.new(ptr, C::Audio.method(:sfMusic_destroy))
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,102 @@
1
+ module SFML
2
+ # A short sound that plays from a SoundBuffer held entirely in memory.
3
+ # Cheap to create, suitable for game SFX (blips, hits, footsteps).
4
+ #
5
+ # buffer = SFML::SoundBuffer.load("blip.wav")
6
+ # sound = SFML::Sound.new(buffer, volume: 80, pitch: 1.2, looping: true)
7
+ # sound.play
8
+ class Sound
9
+ def initialize(buffer, volume: 100.0, pitch: 1.0, looping: false)
10
+ raise ArgumentError, "Sound requires a SFML::SoundBuffer" unless buffer.is_a?(SoundBuffer)
11
+
12
+ ptr = C::Audio.sfSound_create(buffer.handle)
13
+ raise Error, "sfSound_create returned NULL" if ptr.null?
14
+ @handle = FFI::AutoPointer.new(ptr, C::Audio.method(:sfSound_destroy))
15
+ @buffer = buffer # keep alive
16
+ # @looping mirrors the loop flag because SFML 3's isLooping reads
17
+ # through an OpenAL source that may be unallocated on systems
18
+ # without an audio device (some CI runners). Caching on the Ruby
19
+ # side keeps observable behaviour deterministic regardless.
20
+ @looping = false
21
+
22
+ self.volume = volume
23
+ self.pitch = pitch
24
+ self.looping = looping
25
+ end
26
+
27
+ attr_reader :buffer
28
+
29
+ def buffer=(new_buffer)
30
+ raise ArgumentError, "Sound#buffer= requires a SFML::SoundBuffer" unless new_buffer.is_a?(SoundBuffer)
31
+ C::Audio.sfSound_setBuffer(@handle, new_buffer.handle)
32
+ @buffer = new_buffer
33
+ end
34
+
35
+ def play = C::Audio.sfSound_play(@handle)
36
+ def pause = C::Audio.sfSound_pause(@handle)
37
+ def stop = C::Audio.sfSound_stop(@handle)
38
+
39
+ def status = C::Audio::STATUSES[C::Audio.sfSound_getStatus(@handle)]
40
+ def playing? = status == :playing
41
+ def paused? = status == :paused
42
+ def stopped? = status == :stopped
43
+
44
+ def looping?
45
+ @looping
46
+ end
47
+
48
+ def looping=(value)
49
+ @looping = value ? true : false
50
+ C::Audio.sfSound_setLooping(@handle, @looping)
51
+ end
52
+
53
+ def volume = C::Audio.sfSound_getVolume(@handle)
54
+
55
+ def volume=(value)
56
+ C::Audio.sfSound_setVolume(@handle, value.to_f)
57
+ end
58
+
59
+ def pitch = C::Audio.sfSound_getPitch(@handle)
60
+
61
+ def pitch=(value)
62
+ C::Audio.sfSound_setPitch(@handle, value.to_f)
63
+ end
64
+
65
+ # ---- 3D positional audio ----
66
+ #
67
+ # Sounds have a 3D position; the SFML::Listener acts as the "ear".
68
+ # Volume falls off with distance from min_distance outward, scaled
69
+ # by attenuation (0 = no falloff, 1 = realistic, higher = sharper).
70
+ # By default a Sound's position is in world coordinates; flip
71
+ # `relative_to_listener = true` and the position becomes relative
72
+ # to the listener — useful for "stuck to the camera" UI sounds.
73
+ #
74
+ # For 2D games, set z = 0 and listener.position to your camera.
75
+ def position
76
+ Vector3.from_native(C::Audio.sfSound_getPosition(@handle))
77
+ end
78
+
79
+ def position=(value)
80
+ vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
81
+ C::Audio.sfSound_setPosition(@handle, vec.to_native_f)
82
+ end
83
+
84
+ def attenuation = C::Audio.sfSound_getAttenuation(@handle)
85
+
86
+ def attenuation=(value)
87
+ C::Audio.sfSound_setAttenuation(@handle, value.to_f)
88
+ end
89
+
90
+ def min_distance = C::Audio.sfSound_getMinDistance(@handle)
91
+
92
+ def min_distance=(value)
93
+ C::Audio.sfSound_setMinDistance(@handle, value.to_f)
94
+ end
95
+
96
+ def relative_to_listener? = C::Audio.sfSound_isRelativeToListener(@handle)
97
+
98
+ def relative_to_listener=(value)
99
+ C::Audio.sfSound_setRelativeToListener(@handle, value ? true : false)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,38 @@
1
+ module SFML
2
+ # Decoded audio data held in memory. Use it to back one or more Sound
3
+ # instances. Loaded from .wav, .ogg, .flac, .mp3 (depends on CSFML build).
4
+ #
5
+ # buffer = SFML::SoundBuffer.load("assets/blip.wav")
6
+ # sound = SFML::Sound.new(buffer)
7
+ # sound.play
8
+ class SoundBuffer
9
+ def self.load(path)
10
+ ptr = C::Audio.sfSoundBuffer_createFromFile(path.to_s)
11
+ raise Error, "Could not load sound buffer from #{path.inspect}" if ptr.null?
12
+ buf = allocate
13
+ buf.send(:_take_ownership, ptr)
14
+ buf
15
+ end
16
+
17
+ def duration = Time.from_native(C::Audio.sfSoundBuffer_getDuration(@handle))
18
+ def sample_rate = C::Audio.sfSoundBuffer_getSampleRate(@handle)
19
+ def channel_count = C::Audio.sfSoundBuffer_getChannelCount(@handle)
20
+
21
+ # Write the buffer out to disk. Format is inferred from the file
22
+ # extension (.wav / .ogg / .flac, depends on what CSFML was built
23
+ # with).
24
+ def save(path)
25
+ ok = C::Audio.sfSoundBuffer_saveToFile(@handle, path.to_s)
26
+ raise Error, "could not save SoundBuffer to #{path.inspect}" unless ok
27
+ path
28
+ end
29
+
30
+ attr_reader :handle # :nodoc:
31
+
32
+ private
33
+
34
+ def _take_ownership(ptr)
35
+ @handle = FFI::AutoPointer.new(ptr, C::Audio.method(:sfSoundBuffer_destroy))
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,71 @@
1
+ module SFML
2
+ # Records audio from the system input (microphone) directly into a
3
+ # SoundBuffer. Quickest path for a "record audio" feature — start,
4
+ # speak, stop, save:
5
+ #
6
+ # recorder = SFML::SoundBufferRecorder.new
7
+ # recorder.start(sample_rate: 44100)
8
+ # sleep 3
9
+ # recorder.stop
10
+ # recorder.buffer.save("memo.wav")
11
+ #
12
+ # Recording requires a working input device; SFML::SoundRecorder.available?
13
+ # tells you whether one is present before you start.
14
+ class SoundBufferRecorder
15
+ def initialize
16
+ ptr = C::Audio.sfSoundBufferRecorder_create
17
+ raise Error, "sfSoundBufferRecorder_create returned NULL" if ptr.null?
18
+ @handle = FFI::AutoPointer.new(ptr, C::Audio.method(:sfSoundBufferRecorder_destroy))
19
+ end
20
+
21
+ # Begin capturing samples at the given sample rate. Returns true on
22
+ # success, false if the device couldn't be opened.
23
+ def start(sample_rate: 44_100)
24
+ C::Audio.sfSoundBufferRecorder_start(@handle, Integer(sample_rate))
25
+ end
26
+
27
+ def stop
28
+ C::Audio.sfSoundBufferRecorder_stop(@handle)
29
+ self
30
+ end
31
+
32
+ def sample_rate
33
+ C::Audio.sfSoundBufferRecorder_getSampleRate(@handle)
34
+ end
35
+
36
+ def channel_count
37
+ C::Audio.sfSoundBufferRecorder_getChannelCount(@handle)
38
+ end
39
+
40
+ def channel_count=(value)
41
+ C::Audio.sfSoundBufferRecorder_setChannelCount(@handle, Integer(value))
42
+ end
43
+
44
+ # The captured audio so far. Returned as a borrowed SoundBuffer
45
+ # owned by the recorder — copy it (via #save or by feeding to a
46
+ # Sound) before destroying the recorder, or build a Sound that
47
+ # outlives the recorder via the buffer's data.
48
+ def buffer
49
+ ptr = C::Audio.sfSoundBufferRecorder_getBuffer(@handle)
50
+ raise Error, "sfSoundBufferRecorder_getBuffer returned NULL" if ptr.null?
51
+ # Borrowed — recorder owns the underlying sf::SoundBuffer.
52
+ buf = SoundBuffer.allocate
53
+ buf.instance_variable_set(:@handle, ptr)
54
+ buf
55
+ end
56
+
57
+ # Currently selected input device name (or nil).
58
+ def device
59
+ name = C::Audio.sfSoundBufferRecorder_getDevice(@handle)
60
+ name unless name.nil? || name.empty?
61
+ end
62
+
63
+ def device=(name)
64
+ ok = C::Audio.sfSoundBufferRecorder_setDevice(@handle, name.to_s)
65
+ raise Error, "could not select recording device #{name.inspect}" unless ok
66
+ name
67
+ end
68
+
69
+ attr_reader :handle # :nodoc:
70
+ end
71
+ end
@@ -0,0 +1,30 @@
1
+ module SFML
2
+ # Static helpers for audio capture. Use SFML::SoundBufferRecorder
3
+ # to actually record; these tell you what hardware is available.
4
+ #
5
+ # SFML::SoundRecorder.available? #=> true / false
6
+ # SFML::SoundRecorder.devices #=> ["alsa_input.pci-...", ...]
7
+ # SFML::SoundRecorder.default_device #=> "alsa_input.pci-..."
8
+ module SoundRecorder
9
+ module_function
10
+
11
+ # Is at least one audio input device present on the host?
12
+ def available?
13
+ C::Audio.sfSoundRecorder_isAvailable
14
+ end
15
+
16
+ def default_device
17
+ C::Audio.sfSoundRecorder_getDefaultDevice
18
+ end
19
+
20
+ # All input devices the OS exposes to SFML, as an Array of String
21
+ # names. Pass any of them to SoundBufferRecorder#device= to switch.
22
+ def devices
23
+ count_buf = FFI::MemoryPointer.new(:size_t)
24
+ array_ptr = C::Audio.sfSoundRecorder_getAvailableDevices(count_buf)
25
+ n = count_buf.read(:size_t)
26
+ return [] if array_ptr.null? || n.zero?
27
+ array_ptr.read_array_of_pointer(n).map { |p| p.read_string }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,106 @@
1
+ module SFML
2
+ module C
3
+ module Audio
4
+ extend FFI::Library
5
+
6
+ ffi_lib LIB_CANDIDATES[:audio]
7
+
8
+ typedef :pointer, :sound_buffer_t
9
+ typedef :pointer, :sound_t
10
+ typedef :pointer, :music_t
11
+
12
+ # sfSoundStatus = { sfStopped, sfPaused, sfPlaying } in that order.
13
+ STATUSES = %i[stopped paused playing].freeze
14
+
15
+ # ---- SoundBuffer ----
16
+ attach_function :sfSoundBuffer_createFromFile, [:string], :sound_buffer_t
17
+ attach_function :sfSoundBuffer_destroy, [:sound_buffer_t], :void
18
+ attach_function :sfSoundBuffer_saveToFile, [:sound_buffer_t, :string], :bool
19
+ attach_function :sfSoundBuffer_getDuration, [:sound_buffer_t], System::Time.by_value
20
+ attach_function :sfSoundBuffer_getSampleRate, [:sound_buffer_t], :uint32
21
+ attach_function :sfSoundBuffer_getChannelCount,[:sound_buffer_t], :uint32
22
+
23
+ # ---- Sound ----
24
+ attach_function :sfSound_create, [:sound_buffer_t], :sound_t
25
+ attach_function :sfSound_destroy, [:sound_t], :void
26
+ attach_function :sfSound_play, [:sound_t], :void
27
+ attach_function :sfSound_pause, [:sound_t], :void
28
+ attach_function :sfSound_stop, [:sound_t], :void
29
+ attach_function :sfSound_setBuffer, [:sound_t, :sound_buffer_t], :void
30
+ attach_function :sfSound_setLooping, [:sound_t, :bool], :void
31
+ attach_function :sfSound_isLooping, [:sound_t], :bool
32
+ attach_function :sfSound_getStatus, [:sound_t], :int
33
+ attach_function :sfSound_setVolume, [:sound_t, :float], :void
34
+ attach_function :sfSound_getVolume, [:sound_t], :float
35
+ attach_function :sfSound_setPitch, [:sound_t, :float], :void
36
+ attach_function :sfSound_getPitch, [:sound_t], :float
37
+
38
+ # 3D positional audio
39
+ attach_function :sfSound_setPosition, [:sound_t, System::Vector3f.by_value], :void
40
+ attach_function :sfSound_getPosition, [:sound_t], System::Vector3f.by_value
41
+ attach_function :sfSound_setMinDistance, [:sound_t, :float], :void
42
+ attach_function :sfSound_getMinDistance, [:sound_t], :float
43
+ attach_function :sfSound_setAttenuation, [:sound_t, :float], :void
44
+ attach_function :sfSound_getAttenuation, [:sound_t], :float
45
+ attach_function :sfSound_setRelativeToListener, [:sound_t, :bool], :void
46
+ attach_function :sfSound_isRelativeToListener, [:sound_t], :bool
47
+
48
+ # ---- Music ----
49
+ attach_function :sfMusic_createFromFile, [:string], :music_t
50
+ attach_function :sfMusic_destroy, [:music_t], :void
51
+ attach_function :sfMusic_play, [:music_t], :void
52
+ attach_function :sfMusic_pause, [:music_t], :void
53
+ attach_function :sfMusic_stop, [:music_t], :void
54
+ attach_function :sfMusic_setLooping, [:music_t, :bool], :void
55
+ attach_function :sfMusic_isLooping, [:music_t], :bool
56
+ attach_function :sfMusic_getStatus, [:music_t], :int
57
+ attach_function :sfMusic_setVolume, [:music_t, :float], :void
58
+ attach_function :sfMusic_getVolume, [:music_t], :float
59
+ attach_function :sfMusic_setPitch, [:music_t, :float], :void
60
+ attach_function :sfMusic_getPitch, [:music_t], :float
61
+ attach_function :sfMusic_getDuration, [:music_t], System::Time.by_value
62
+
63
+ attach_function :sfMusic_setPosition, [:music_t, System::Vector3f.by_value], :void
64
+ attach_function :sfMusic_getPosition, [:music_t], System::Vector3f.by_value
65
+ attach_function :sfMusic_setMinDistance, [:music_t, :float], :void
66
+ attach_function :sfMusic_getMinDistance, [:music_t], :float
67
+ attach_function :sfMusic_setAttenuation, [:music_t, :float], :void
68
+ attach_function :sfMusic_getAttenuation, [:music_t], :float
69
+ attach_function :sfMusic_setRelativeToListener, [:music_t, :bool], :void
70
+ attach_function :sfMusic_isRelativeToListener, [:music_t], :bool
71
+
72
+ # ---- SoundBufferRecorder ----
73
+ # The simple "record into a SoundBuffer" path. Raw sfSoundRecorder
74
+ # (callback-based) and sfSoundStream (custom audio source via
75
+ # callbacks) need Ruby callbacks running on the SFML audio thread —
76
+ # not worth the complexity for a niche feature.
77
+ typedef :pointer, :sound_buffer_recorder_t
78
+
79
+ attach_function :sfSoundBufferRecorder_create, [], :sound_buffer_recorder_t
80
+ attach_function :sfSoundBufferRecorder_destroy, [:sound_buffer_recorder_t], :void
81
+ attach_function :sfSoundBufferRecorder_start, [:sound_buffer_recorder_t, :uint32], :bool
82
+ attach_function :sfSoundBufferRecorder_stop, [:sound_buffer_recorder_t], :void
83
+ attach_function :sfSoundBufferRecorder_getSampleRate, [:sound_buffer_recorder_t], :uint32
84
+ attach_function :sfSoundBufferRecorder_getBuffer, [:sound_buffer_recorder_t], :sound_buffer_t
85
+ attach_function :sfSoundBufferRecorder_setDevice, [:sound_buffer_recorder_t, :string], :bool
86
+ attach_function :sfSoundBufferRecorder_getDevice, [:sound_buffer_recorder_t], :string
87
+ attach_function :sfSoundBufferRecorder_setChannelCount, [:sound_buffer_recorder_t, :uint32], :void
88
+ attach_function :sfSoundBufferRecorder_getChannelCount, [:sound_buffer_recorder_t], :uint32
89
+
90
+ # SoundRecorder static helpers — query mic availability and devices.
91
+ attach_function :sfSoundRecorder_isAvailable, [], :bool
92
+ attach_function :sfSoundRecorder_getDefaultDevice, [], :string
93
+ attach_function :sfSoundRecorder_getAvailableDevices, [:pointer], :pointer
94
+
95
+ # ---- Listener (the "ear" — global, no handle) ----
96
+ attach_function :sfListener_setGlobalVolume, [:float], :void
97
+ attach_function :sfListener_getGlobalVolume, [], :float
98
+ attach_function :sfListener_setPosition, [System::Vector3f.by_value], :void
99
+ attach_function :sfListener_getPosition, [], System::Vector3f.by_value
100
+ attach_function :sfListener_setDirection, [System::Vector3f.by_value], :void
101
+ attach_function :sfListener_getDirection, [], System::Vector3f.by_value
102
+ attach_function :sfListener_setUpVector, [System::Vector3f.by_value], :void
103
+ attach_function :sfListener_getUpVector, [], System::Vector3f.by_value
104
+ end
105
+ end
106
+ end