ogg-ruby 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '05859e9062f2f93116ce07130ae3af402a2065027956733c88dc7dbe90f32efb'
4
+ data.tar.gz: 33ed5b81ba61efa72ef8d318a888b28ed84ee729b26f9eb595a10143df8a4630
5
+ SHA512:
6
+ metadata.gz: c3d5fdd2167a1b3a200484e3d8a5538b3e3a467f024777614be8f1b594702418eb3e5b04c156f3197f824566fb16a00285144ec3f7537aedb64217a323aed53f
7
+ data.tar.gz: 7ef459bdbe68ac85d88c3d28151cfd83fb7dc0e033901d5794522e0d3162f0a04dcf1aceb844d0bce451c84e02c61173c71ffb8ec71ec2ce34dfbffa79e69e7e
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on Keep a Changelog and this project follows Semantic Versioning.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## 0.1.0 (2026-02-28)
10
+
11
+ - Initial release.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Yudai Takada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # ogg-ruby
2
+
3
+ Ruby FFI bindings for [libogg](https://xiph.org/ogg/), the OGG container format library.
4
+
5
+ ## Requirements
6
+
7
+ - Ruby 3.1+
8
+ - libogg installed on your system
9
+
10
+ ### Installing libogg
11
+
12
+ **macOS:**
13
+
14
+ ```bash
15
+ brew install libogg
16
+ ```
17
+
18
+ **Debian/Ubuntu:**
19
+
20
+ ```bash
21
+ sudo apt-get install libogg-dev
22
+ ```
23
+
24
+ **Fedora/RHEL:**
25
+
26
+ ```bash
27
+ sudo dnf install libogg-devel
28
+ ```
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ ```ruby
35
+ gem "ogg-ruby"
36
+ ```
37
+
38
+ And then execute:
39
+
40
+ ```bash
41
+ bundle install
42
+ ```
43
+
44
+ Or install it yourself as:
45
+
46
+ ```bash
47
+ gem install ogg-ruby
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ### Encoding (Packet → StreamState → Page)
53
+
54
+ ```ruby
55
+ require "ogg"
56
+
57
+ stream = Ogg::StreamState.new(1) # serial number
58
+
59
+ # Add packets to the stream
60
+ packet = Ogg::Packet.new(data: "Hello, OGG!", bos: true, granulepos: 0, packetno: 0)
61
+ stream.packetin(packet)
62
+
63
+ packet2 = Ogg::Packet.new(data: "More data", eos: true, granulepos: 1, packetno: 1)
64
+ stream.packetin(packet2)
65
+
66
+ # Extract pages
67
+ pages = []
68
+ while (page = stream.flush)
69
+ pages << page.to_s
70
+ end
71
+
72
+ stream.clear
73
+ ```
74
+
75
+ ### Decoding (SyncState → Page → StreamState → Packet)
76
+
77
+ ```ruby
78
+ require "ogg"
79
+
80
+ sync = Ogg::SyncState.new
81
+
82
+ # Write encoded data into sync
83
+ sync.write(encoded_page_data)
84
+
85
+ # Extract pages
86
+ while (page = sync.pageout)
87
+ # Create a stream decoder with the same serial number
88
+ stream = Ogg::StreamState.new(page.serialno)
89
+ stream.pagein(page)
90
+
91
+ # Extract packets
92
+ while (packet = stream.packetout)
93
+ puts packet.data
94
+ end
95
+
96
+ stream.clear
97
+ end
98
+
99
+ sync.clear
100
+ ```
101
+
102
+ ## Thread Safety
103
+
104
+ libogg functions are not thread-safe. Do not share `SyncState` or `StreamState` objects across threads without external synchronization.
105
+
106
+ ## License
107
+
108
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/lib/ogg/native.rb ADDED
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ module Native
5
+ extend FFI::Library
6
+ ffi_lib ["libogg.so.0", "libogg.0.dylib", "libogg", "ogg"]
7
+
8
+ # --- Structs ---
9
+
10
+ class OggSyncState < FFI::Struct
11
+ layout :data, :pointer,
12
+ :storage, :int,
13
+ :fill, :int,
14
+ :returned, :int,
15
+ :unsynced, :int,
16
+ :headerbytes, :int,
17
+ :bodybytes, :int
18
+ end
19
+
20
+ class OggStreamState < FFI::Struct
21
+ layout :body_data, :pointer,
22
+ :body_storage, :long,
23
+ :body_fill, :long,
24
+ :body_returned, :long,
25
+ :lacing_vals, :pointer,
26
+ :granule_vals, :pointer,
27
+ :lacing_storage, :long,
28
+ :lacing_fill, :long,
29
+ :lacing_packet, :long,
30
+ :lacing_returned, :long,
31
+ :header, [:uchar, 282],
32
+ :header_fill, :int,
33
+ :e_o_s, :int,
34
+ :b_o_s, :int,
35
+ :serialno, :long,
36
+ :pageno, :long,
37
+ :packetno, :int64,
38
+ :granulepos, :int64
39
+ end
40
+
41
+ class OggPage < FFI::Struct
42
+ layout :header, :pointer,
43
+ :header_len, :long,
44
+ :body, :pointer,
45
+ :body_len, :long
46
+ end
47
+
48
+ class OggPacket < FFI::Struct
49
+ layout :packet, :pointer,
50
+ :bytes, :long,
51
+ :b_o_s, :long,
52
+ :e_o_s, :long,
53
+ :granulepos, :int64,
54
+ :packetno, :int64
55
+ end
56
+
57
+ # --- Sync API ---
58
+
59
+ attach_function :ogg_sync_init, [:pointer], :int
60
+ attach_function :ogg_sync_clear, [:pointer], :int
61
+ attach_function :ogg_sync_reset, [:pointer], :int
62
+ attach_function :ogg_sync_buffer, [:pointer, :long], :pointer
63
+ attach_function :ogg_sync_wrote, [:pointer, :long], :int
64
+ attach_function :ogg_sync_pageout, [:pointer, :pointer], :int
65
+ attach_function :ogg_sync_pageseek, [:pointer, :pointer], :long
66
+
67
+ # --- Stream API ---
68
+
69
+ attach_function :ogg_stream_init, [:pointer, :int], :int
70
+ attach_function :ogg_stream_clear, [:pointer], :int
71
+ attach_function :ogg_stream_reset, [:pointer], :int
72
+ attach_function :ogg_stream_reset_serialno, [:pointer, :int], :int
73
+ attach_function :ogg_stream_packetin, [:pointer, :pointer], :int
74
+ attach_function :ogg_stream_pageout, [:pointer, :pointer], :int
75
+ attach_function :ogg_stream_pageout_fill, [:pointer, :pointer, :int], :int
76
+ attach_function :ogg_stream_flush, [:pointer, :pointer], :int
77
+ attach_function :ogg_stream_flush_fill, [:pointer, :pointer, :int], :int
78
+ attach_function :ogg_stream_pagein, [:pointer, :pointer], :int
79
+ attach_function :ogg_stream_packetout, [:pointer, :pointer], :int
80
+ attach_function :ogg_stream_packetpeek, [:pointer, :pointer], :int
81
+ attach_function :ogg_stream_eos, [:pointer], :int
82
+
83
+ # --- Page API ---
84
+
85
+ attach_function :ogg_page_version, [:pointer], :int
86
+ attach_function :ogg_page_continued, [:pointer], :int
87
+ attach_function :ogg_page_bos, [:pointer], :int
88
+ attach_function :ogg_page_eos, [:pointer], :int
89
+ attach_function :ogg_page_granulepos, [:pointer], :int64
90
+ attach_function :ogg_page_serialno, [:pointer], :int
91
+ attach_function :ogg_page_pageno, [:pointer], :long
92
+ attach_function :ogg_page_packets, [:pointer], :int
93
+ attach_function :ogg_page_checksum_set, [:pointer], :void
94
+
95
+ # --- Packet API ---
96
+
97
+ attach_function :ogg_packet_clear, [:pointer], :void
98
+ end
99
+ end
data/lib/ogg/packet.rb ADDED
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ class Packet
5
+ attr_reader :native
6
+
7
+ def initialize(data: nil, bos: false, eos: false, granulepos: 0, packetno: 0, owner: nil)
8
+ @owner = owner
9
+ @ptr = FFI::MemoryPointer.new(Native::OggPacket.size)
10
+ @native = Native::OggPacket.new(@ptr)
11
+
12
+ if data
13
+ @data_ptr = FFI::MemoryPointer.new(:uint8, data.bytesize)
14
+ @data_ptr.put_bytes(0, data)
15
+ @native[:packet] = @data_ptr
16
+ @native[:bytes] = data.bytesize
17
+ @native[:b_o_s] = bos ? 1 : 0
18
+ @native[:e_o_s] = eos ? 1 : 0
19
+ @native[:granulepos] = granulepos
20
+ @native[:packetno] = packetno
21
+ end
22
+ end
23
+
24
+ def data
25
+ ensure_owner_active!
26
+ length = @native[:bytes]
27
+ raise Error, "packet bytes cannot be negative" if length.negative?
28
+ return +"".b if length.zero?
29
+
30
+ pointer = @native[:packet]
31
+ raise Error, "packet pointer is null while bytes=#{length}" if pointer.null?
32
+
33
+ pointer.read_bytes(length)
34
+ end
35
+
36
+ def bytes
37
+ @native[:bytes]
38
+ end
39
+
40
+ def bos?
41
+ @native[:b_o_s] != 0
42
+ end
43
+
44
+ def eos?
45
+ @native[:e_o_s] != 0
46
+ end
47
+
48
+ def granulepos
49
+ @native[:granulepos]
50
+ end
51
+
52
+ def packetno
53
+ @native[:packetno]
54
+ end
55
+
56
+ private
57
+
58
+ def ensure_owner_active!
59
+ return unless @owner&.cleared?
60
+
61
+ raise ReleasedResourceError, "cannot read packet data after owner state is cleared"
62
+ end
63
+ end
64
+ end
data/lib/ogg/page.rb ADDED
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ class Page
5
+ attr_reader :native
6
+
7
+ def initialize(native_page = nil, owner: nil)
8
+ @owner = owner
9
+ if native_page
10
+ @ptr = native_page
11
+ @native = native_page.is_a?(Native::OggPage) ? native_page : Native::OggPage.new(native_page)
12
+ else
13
+ @ptr = FFI::MemoryPointer.new(Native::OggPage.size)
14
+ @native = Native::OggPage.new(@ptr)
15
+ end
16
+ end
17
+
18
+ def version
19
+ ensure_owner_active!
20
+ Native.ogg_page_version(@ptr)
21
+ end
22
+
23
+ def continued?
24
+ ensure_owner_active!
25
+ Native.ogg_page_continued(@ptr) != 0
26
+ end
27
+
28
+ def bos?
29
+ ensure_owner_active!
30
+ Native.ogg_page_bos(@ptr) != 0
31
+ end
32
+
33
+ def eos?
34
+ ensure_owner_active!
35
+ Native.ogg_page_eos(@ptr) != 0
36
+ end
37
+
38
+ def granulepos
39
+ ensure_owner_active!
40
+ Native.ogg_page_granulepos(@ptr)
41
+ end
42
+
43
+ def serialno
44
+ ensure_owner_active!
45
+ Native.ogg_page_serialno(@ptr)
46
+ end
47
+
48
+ def pageno
49
+ ensure_owner_active!
50
+ Native.ogg_page_pageno(@ptr)
51
+ end
52
+
53
+ def packets
54
+ ensure_owner_active!
55
+ Native.ogg_page_packets(@ptr)
56
+ end
57
+
58
+ def header_data
59
+ read_segment(:header, :header_len)
60
+ end
61
+
62
+ def body_data
63
+ read_segment(:body, :body_len)
64
+ end
65
+
66
+ def to_s
67
+ header_data + body_data
68
+ end
69
+
70
+ private
71
+
72
+ def read_segment(pointer_field, length_field)
73
+ ensure_owner_active!
74
+ length = @native[length_field]
75
+ raise Error, "#{length_field} cannot be negative" if length.negative?
76
+ return +"".b if length.zero?
77
+
78
+ pointer = @native[pointer_field]
79
+ raise Error, "#{pointer_field} is null while #{length_field}=#{length}" if pointer.null?
80
+
81
+ pointer.read_bytes(length)
82
+ end
83
+
84
+ def ensure_owner_active!
85
+ return unless @owner&.cleared?
86
+
87
+ raise ReleasedResourceError, "cannot read page data after owner state is cleared"
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ class StreamState
5
+ attr_reader :serialno
6
+
7
+ def initialize(serialno)
8
+ @serialno = serialno
9
+ @ptr = FFI::MemoryPointer.new(Native::OggStreamState.size)
10
+ result = Native.ogg_stream_init(@ptr, serialno)
11
+ raise StreamError, "ogg_stream_init failed with status #{result}" unless result == 0
12
+
13
+ @clear_state = [false]
14
+ ObjectSpace.define_finalizer(self, self.class.finalizer_for(@ptr, @clear_state))
15
+ end
16
+
17
+ def packetin(packet)
18
+ ensure_active!
19
+ result = Native.ogg_stream_packetin(@ptr, packet.native)
20
+ raise StreamError, "ogg_stream_packetin failed with status #{result}" unless result == 0
21
+ end
22
+
23
+ def pageout
24
+ ensure_active!
25
+ page = Page.new(owner: self)
26
+ result = Native.ogg_stream_pageout(@ptr, page.native)
27
+ case result
28
+ when 1 then page
29
+ when 0 then nil
30
+ when -1 then raise StreamCorruptDataError, "ogg_stream_pageout detected stream corruption"
31
+ else raise StreamError, "ogg_stream_pageout returned unexpected status #{result}"
32
+ end
33
+ end
34
+
35
+ def flush
36
+ ensure_active!
37
+ page = Page.new(owner: self)
38
+ result = Native.ogg_stream_flush(@ptr, page.native)
39
+ case result
40
+ when 1 then page
41
+ when 0 then nil
42
+ when -1 then raise StreamCorruptDataError, "ogg_stream_flush detected stream corruption"
43
+ else raise StreamError, "ogg_stream_flush returned unexpected status #{result}"
44
+ end
45
+ end
46
+
47
+ def pagein(page)
48
+ ensure_active!
49
+ result = Native.ogg_stream_pagein(@ptr, page.native)
50
+ case result
51
+ when 0 then nil
52
+ when -1 then raise StreamCorruptDataError, "ogg_stream_pagein detected stream corruption"
53
+ else raise StreamError, "ogg_stream_pagein failed with status #{result}"
54
+ end
55
+ end
56
+
57
+ def packetout
58
+ ensure_active!
59
+ packet = Packet.new(owner: self)
60
+ result = Native.ogg_stream_packetout(@ptr, packet.native)
61
+ case result
62
+ when 1 then packet
63
+ when 0 then nil
64
+ when -1 then raise StreamCorruptDataError, "ogg_stream_packetout detected a hole in the stream"
65
+ else raise StreamError, "ogg_stream_packetout returned unexpected status #{result}"
66
+ end
67
+ end
68
+
69
+ def packetpeek
70
+ ensure_active!
71
+ packet = Packet.new(owner: self)
72
+ result = Native.ogg_stream_packetpeek(@ptr, packet.native)
73
+ case result
74
+ when 1 then packet
75
+ when 0 then nil
76
+ when -1 then raise StreamCorruptDataError, "ogg_stream_packetpeek detected a hole in the stream"
77
+ else raise StreamError, "ogg_stream_packetpeek returned unexpected status #{result}"
78
+ end
79
+ end
80
+
81
+ def eos?
82
+ ensure_active!
83
+ result = Native.ogg_stream_eos(@ptr)
84
+ case result
85
+ when 0 then false
86
+ when 1 then true
87
+ else
88
+ raise StreamError, "ogg_stream_eos returned unexpected status #{result}"
89
+ end
90
+ end
91
+
92
+ def reset
93
+ ensure_active!
94
+ result = Native.ogg_stream_reset(@ptr)
95
+ raise StreamError, "ogg_stream_reset failed with status #{result}" unless result == 0
96
+ end
97
+
98
+ def reset_serialno(serialno)
99
+ ensure_active!
100
+ result = Native.ogg_stream_reset_serialno(@ptr, serialno)
101
+ raise StreamError, "ogg_stream_reset_serialno failed with status #{result}" unless result == 0
102
+
103
+ @serialno = serialno
104
+ end
105
+
106
+ def clear
107
+ return if cleared?
108
+
109
+ result = Native.ogg_stream_clear(@ptr)
110
+ raise StreamError, "ogg_stream_clear failed with status #{result}" unless result == 0
111
+
112
+ @clear_state[0] = true
113
+ end
114
+
115
+ def cleared?
116
+ @clear_state[0]
117
+ end
118
+
119
+ def self.finalizer_for(ptr, clear_state)
120
+ proc do
121
+ Native.ogg_stream_clear(ptr) unless clear_state[0]
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def ensure_active!
128
+ return unless cleared?
129
+
130
+ raise ReleasedResourceError, "stream state has been cleared"
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ class SyncState
5
+ def initialize
6
+ @ptr = FFI::MemoryPointer.new(Native::OggSyncState.size)
7
+ result = Native.ogg_sync_init(@ptr)
8
+ raise SyncError, "ogg_sync_init failed with status #{result}" unless result == 0
9
+
10
+ @clear_state = [false]
11
+ ObjectSpace.define_finalizer(self, self.class.finalizer_for(@ptr, @clear_state))
12
+ end
13
+
14
+ def write(data)
15
+ ensure_active!
16
+ buffer = Native.ogg_sync_buffer(@ptr, data.bytesize)
17
+ raise SyncError, "ogg_sync_buffer returned null" if buffer.null?
18
+
19
+ buffer.put_bytes(0, data)
20
+ result = Native.ogg_sync_wrote(@ptr, data.bytesize)
21
+ raise SyncError, "ogg_sync_wrote failed with status #{result}" unless result == 0
22
+ end
23
+
24
+ def pageout
25
+ ensure_active!
26
+ page = Page.new(owner: self)
27
+ result = Native.ogg_sync_pageout(@ptr, page.native)
28
+ case result
29
+ when 1 then page
30
+ when 0 then nil
31
+ when -1 then raise SyncCorruptDataError, "ogg_sync_pageout detected unsynced/corrupt data"
32
+ else raise SyncError, "ogg_sync_pageout returned unexpected status #{result}"
33
+ end
34
+ end
35
+
36
+ def reset
37
+ ensure_active!
38
+ result = Native.ogg_sync_reset(@ptr)
39
+ raise SyncError, "ogg_sync_reset failed with status #{result}" unless result == 0
40
+ end
41
+
42
+ def clear
43
+ return if cleared?
44
+
45
+ result = Native.ogg_sync_clear(@ptr)
46
+ raise SyncError, "ogg_sync_clear failed with status #{result}" unless result == 0
47
+
48
+ @clear_state[0] = true
49
+ end
50
+
51
+ def cleared?
52
+ @clear_state[0]
53
+ end
54
+
55
+ def self.finalizer_for(ptr, clear_state)
56
+ proc do
57
+ Native.ogg_sync_clear(ptr) unless clear_state[0]
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def ensure_active!
64
+ return unless cleared?
65
+
66
+ raise ReleasedResourceError, "sync state has been cleared"
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ogg
4
+ VERSION = "0.1.0"
5
+ end
data/lib/ogg.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+ require_relative "ogg/version"
5
+ require_relative "ogg/native"
6
+ require_relative "ogg/page"
7
+ require_relative "ogg/packet"
8
+ require_relative "ogg/sync_state"
9
+ require_relative "ogg/stream_state"
10
+
11
+ module Ogg
12
+ class Error < StandardError; end
13
+ class ReleasedResourceError < Error; end
14
+ class CorruptDataError < Error; end
15
+ class SyncError < Error; end
16
+ class SyncCorruptDataError < SyncError; end
17
+ class StreamError < Error; end
18
+ class StreamCorruptDataError < StreamError; end
19
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ogg-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yudai Takada
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ffi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.15'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.15'
26
+ description: A Ruby FFI binding library for libogg, providing OGG container format
27
+ stream operations (page read/write, packet assembly/disassembly).
28
+ email:
29
+ - t.yudai92@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CHANGELOG.md
35
+ - LICENSE.txt
36
+ - README.md
37
+ - Rakefile
38
+ - lib/ogg.rb
39
+ - lib/ogg/native.rb
40
+ - lib/ogg/packet.rb
41
+ - lib/ogg/page.rb
42
+ - lib/ogg/stream_state.rb
43
+ - lib/ogg/sync_state.rb
44
+ - lib/ogg/version.rb
45
+ homepage: https://github.com/ydah/ogg-ruby
46
+ licenses:
47
+ - MIT
48
+ metadata:
49
+ homepage_uri: https://github.com/ydah/ogg-ruby
50
+ source_code_uri: https://github.com/ydah/ogg-ruby
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 3.1.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 4.0.6
66
+ specification_version: 4
67
+ summary: Ruby FFI bindings for libogg
68
+ test_files: []