Class: SFML::InputStream

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/system/input_stream.rb

Overview

Bridge between a Ruby IO-like object (anything with ‘#read(n)`, `#seek(pos)`, `#pos` / `#tell`, and `#size`) and CSFML’s ‘sfInputStream*` parameter on `*_createFromStream` loader functions.

Typical use is indirect — pass a Ruby IO to the ‘.from_stream` factory on Font, Image, Texture, Shader, Music, or SoundBuffer:

File.open("assets/hero.png", "rb") do |io|
  tex = SFML::Texture.from_stream(io)
end

Direct use is for advanced cases (custom virtual filesystems, network streams, etc.). Subclass or build with ‘.new(io)`:

wrapped = SFML::InputStream.new(my_random_access_io)
font    = SFML::Font.send(:_load_from_stream_handle, wrapped.struct)

The InputStream object must outlive the loader call — keep a reference until the CSFML factory returns. The wrapped IO is not closed automatically; close it yourself.

Instance Method Summary collapse

Constructor Details

#initialize(io) ⇒ InputStream

‘io` must respond to: read(n), seek(pos, IO::SEEK_SET), pos/tell, size. Ruby’s File, StringIO, and Tempfile all qualify.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/sfml/system/input_stream.rb', line 27

def initialize(io)
  @io = io

  # Strong refs so the GC doesn't free our callbacks before CSFML
  # is done with the struct. CSFML calls them synchronously
  # during the loader function, but may also call them later
  # (Music streams from disk on its audio thread).
  @read_cb = FFI::Function.new(:int64, [:pointer, :size_t, :pointer]) do |buf, size, _user|
    begin
      bytes = @io.read(size) || ""
      buf.write_bytes(bytes) unless bytes.empty?
      bytes.bytesize
    rescue StandardError
      -1
    end
  end

  @seek_cb = FFI::Function.new(:int64, [:size_t, :pointer]) do |pos, _user|
    begin
      @io.seek(pos, IO::SEEK_SET)
      pos
    rescue StandardError
      -1
    end
  end

  @tell_cb = FFI::Function.new(:int64, [:pointer]) do |_user|
    begin
      @io.respond_to?(:pos) ? @io.pos : @io.tell
    rescue StandardError
      -1
    end
  end

  @size_cb = FFI::Function.new(:int64, [:pointer]) do |_user|
    begin
      @io.size
    rescue StandardError
      -1
    end
  end

  @struct = C::System::InputStream.new
  @struct[:read]      = @read_cb
  @struct[:seek]      = @seek_cb
  @struct[:tell]      = @tell_cb
  @struct[:get_size]  = @size_cb
  @struct[:user_data] = FFI::Pointer::NULL
end

Instance Method Details

#to_ptrObject

Pointer suitable for the ‘sfInputStream*` parameter on `*_createFromStream` loaders.



84
85
86
# File 'lib/sfml/system/input_stream.rb', line 84

def to_ptr
  @struct.pointer
end