wahwah 0.1.0.pre.test → 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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +22 -0
  6. data/README.md +35 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/lib/wahwah.rb +3 -74
  11. data/lib/wahwah/version.rb +2 -4
  12. data/wahwah.gemspec +27 -0
  13. metadata +25 -96
  14. data/LICENSE +0 -21
  15. data/lib/wahwah/asf/object.rb +0 -39
  16. data/lib/wahwah/asf_tag.rb +0 -220
  17. data/lib/wahwah/errors.rb +0 -6
  18. data/lib/wahwah/flac/block.rb +0 -57
  19. data/lib/wahwah/flac/streaminfo_block.rb +0 -51
  20. data/lib/wahwah/flac_tag.rb +0 -84
  21. data/lib/wahwah/helper.rb +0 -37
  22. data/lib/wahwah/id3/comment_frame_body.rb +0 -21
  23. data/lib/wahwah/id3/frame.rb +0 -180
  24. data/lib/wahwah/id3/frame_body.rb +0 -36
  25. data/lib/wahwah/id3/genre_frame_body.rb +0 -15
  26. data/lib/wahwah/id3/image_frame_body.rb +0 -60
  27. data/lib/wahwah/id3/text_frame_body.rb +0 -16
  28. data/lib/wahwah/id3/v1.rb +0 -96
  29. data/lib/wahwah/id3/v2.rb +0 -60
  30. data/lib/wahwah/id3/v2_header.rb +0 -53
  31. data/lib/wahwah/mp3/mpeg_frame_header.rb +0 -141
  32. data/lib/wahwah/mp3/vbri_header.rb +0 -47
  33. data/lib/wahwah/mp3/xing_header.rb +0 -45
  34. data/lib/wahwah/mp3_tag.rb +0 -110
  35. data/lib/wahwah/mp4/atom.rb +0 -105
  36. data/lib/wahwah/mp4_tag.rb +0 -126
  37. data/lib/wahwah/ogg/flac_tag.rb +0 -37
  38. data/lib/wahwah/ogg/opus_tag.rb +0 -33
  39. data/lib/wahwah/ogg/packets.rb +0 -41
  40. data/lib/wahwah/ogg/page.rb +0 -121
  41. data/lib/wahwah/ogg/pages.rb +0 -24
  42. data/lib/wahwah/ogg/vorbis_comment.rb +0 -51
  43. data/lib/wahwah/ogg/vorbis_tag.rb +0 -35
  44. data/lib/wahwah/ogg_tag.rb +0 -66
  45. data/lib/wahwah/riff/chunk.rb +0 -54
  46. data/lib/wahwah/riff_tag.rb +0 -140
  47. data/lib/wahwah/tag.rb +0 -59
  48. data/lib/wahwah/tag_delegate.rb +0 -16
data/lib/wahwah/helper.rb DELETED
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module Helper
5
- def self.encode_to_utf8(string, source_encoding: '')
6
- encoded_string = source_encoding.empty? ?
7
- string.force_encoding('utf-8') :
8
- string.encode('utf-8', source_encoding, invalid: :replace, undef: :replace, replace: '')
9
-
10
- encoded_string.valid_encoding? ? encoded_string.strip : ''
11
- end
12
-
13
- # ID3 size is encoded with four bytes where may the most significant
14
- # bit (bit 7) is set to zero in every byte,
15
- # making a total of 28 bits. The zeroed bits are ignored
16
- def self.id3_size_caculate(bits_string, has_zero_bit: true)
17
- if has_zero_bit
18
- bits_string.scan(/.{8}/).map { |byte_string| byte_string[1..-1] }.join.to_i(2)
19
- else
20
- bits_string.to_i(2)
21
- end
22
- end
23
-
24
- def self.split_with_terminator(string, terminator_size)
25
- string.split(Regexp.new(('\x00' * terminator_size).b), 2)
26
- end
27
-
28
- def self.file_format(file_path)
29
- File.extname(file_path).downcase.delete('.')
30
- end
31
-
32
- def self.byte_string_to_guid(byte_string)
33
- guid = byte_string.unpack('NnnA*').pack('VvvA*').unpack('H*').first
34
- [guid[0..7], guid[8..11], guid[12..15], guid[16..19], guid[20..-1]].join('-').upcase
35
- end
36
- end
37
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class CommentFrameBody < FrameBody
6
- # Comment frame body structure:
7
- #
8
- # Text encoding $xx
9
- # Language $xx xx xx
10
- # Short content description <textstring> $00 (00)
11
- # The actual text <textstring>
12
- def parse
13
- encoding_id, _language, reset_content = @content.unpack('CA3a*')
14
- encoding = ENCODING_MAPPING[encoding_id]
15
- _description, comment_text = Helper.split_with_terminator(reset_content, ENCODING_TERMINATOR_SIZE[encoding])
16
-
17
- @value = Helper.encode_to_utf8(comment_text, source_encoding: encoding)
18
- end
19
- end
20
- end
21
- end
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'zlib'
4
-
5
- module WahWah
6
- module ID3
7
- class Frame
8
- ID_MAPPING = {
9
- # ID3v2.2 frame id
10
- COM: :comment,
11
- TRK: :track,
12
- TYE: :year,
13
- TAL: :album,
14
- TP1: :artist,
15
- TT2: :title,
16
- TCO: :genre,
17
- TPA: :disc,
18
- TP2: :albumartist,
19
- TCM: :composer,
20
- PIC: :image,
21
-
22
- # ID3v2.3 and ID3v2.4 frame id
23
- COMM: :comment,
24
- TRCK: :track,
25
- TYER: :year,
26
- TALB: :album,
27
- TPE1: :artist,
28
- TIT2: :title,
29
- TCON: :genre,
30
- TPOS: :disc,
31
- TPE2: :albumartist,
32
- TCOM: :composer,
33
- APIC: :image,
34
-
35
- # ID3v2.4 use TDRC replace TYER
36
- TDRC: :year
37
- }
38
-
39
- # ID3v2.3 frame flags field is defined as follows.
40
- #
41
- # %abc00000 %ijk00000
42
- #
43
- # a - Tag alter preservation
44
- # b - File alter preservation
45
- # c - Read only
46
- # i - Compression
47
- # j - Encryption
48
- # k - Grouping identity
49
- V3_HEADER_FLAGS_INDICATIONS = Array.new(16).tap do |array|
50
- array[0] = :tag_alter_preservation
51
- array[1] = :file_alter_preservation
52
- array[2] = :read_only
53
- array[8] = :compression
54
- array[9] = :encryption
55
- array[10] = :grouping_identity
56
- end
57
-
58
- # ID3v2.4 frame flags field is defined as follows.
59
- #
60
- # %0abc0000 %0h00kmnp
61
- #
62
- # a - Tag alter preservation
63
- # b - File alter preservation
64
- # c - Read only
65
- # h - Grouping identity
66
- # k - Compression
67
- # m - Encryption
68
- # n - Unsynchronisation
69
- # p - Data length indicator
70
- V4_HEADER_FLAGS_INDICATIONS = Array.new(16).tap do |array|
71
- array[1] = :tag_alter_preservation
72
- array[2] = :file_alter_preservation
73
- array[3] = :read_only
74
- array[9] = :grouping_identity
75
- array[12] = :compression
76
- array[13] = :encryption
77
- array[14] = :unsynchronisation
78
- array[15] = :data_length_indicator
79
- end
80
-
81
- attr_reader :name, :value
82
-
83
- def initialize(file_io, version)
84
- @file_io = file_io
85
- @version = version
86
-
87
- parse_frame_header
88
-
89
- # In ID3v2.3 when frame is compressed using zlib
90
- # with 4 bytes for 'decompressed size' appended to the frame header.
91
- #
92
- # In ID3v2.4 A 'Data Length Indicator' byte MUST be included in the frame
93
- # when frame is compressed, and 'Data Length Indicator'represented as a 32 bit
94
- # synchsafe integer
95
- #
96
- # So skip those 4 byte.
97
- if compressed? || data_length_indicator?
98
- @file_io.seek(4, IO::SEEK_CUR)
99
- @size = @size - 4
100
- end
101
-
102
- parse_body
103
- end
104
-
105
- def valid?
106
- @size > 0 && !@name.nil?
107
- end
108
-
109
- def compressed?
110
- @flags.include? :compression
111
- end
112
-
113
- def data_length_indicator?
114
- @flags.include? :data_length_indicator
115
- end
116
-
117
-
118
- private
119
- # ID3v2.2 frame header structure:
120
- #
121
- # Frame ID $xx xx xx(tree characters)
122
- # Size 3 * %xxxxxxxx
123
- #
124
- # ID3v2.3 frame header structure:
125
- #
126
- # Frame ID $xx xx xx xx (four characters)
127
- # Size 4 * %xxxxxxxx
128
- # Flags $xx xx
129
- #
130
- # ID3v2.4 frame header structure:
131
- #
132
- # Frame ID $xx xx xx xx (four characters)
133
- # Size 4 * %0xxxxxxx
134
- # Flags $xx xx
135
- def parse_frame_header
136
- header_size = @version == 2 ? 6 : 10
137
- header_formate = @version == 2 ? 'A3B24' : 'A4B32B16'
138
- id, size_bits, flags_bits = @file_io.read(header_size).unpack(header_formate)
139
-
140
- @name = ID_MAPPING[id.to_sym]
141
- @size = Helper.id3_size_caculate(size_bits, has_zero_bit: @version == 4)
142
- @flags = parse_flags(flags_bits)
143
- end
144
-
145
- def parse_flags(flags_bits)
146
- return [] if flags_bits.nil?
147
-
148
- frame_flags_indications = @version == 4 ?
149
- V4_HEADER_FLAGS_INDICATIONS :
150
- V3_HEADER_FLAGS_INDICATIONS
151
-
152
- flags_bits.split('').map.with_index do |flag_bit, index|
153
- frame_flags_indications[index] if flag_bit == '1'
154
- end.compact
155
- end
156
-
157
- def parse_body
158
- return unless @size > 0
159
- (@file_io.seek(@size, IO::SEEK_CUR); return) if @name.nil?
160
-
161
- content = compressed? ? Zlib.inflate(@file_io.read(@size)) : @file_io.read(@size)
162
- frame_body = frame_body_class.new(content, @version)
163
- @value = frame_body.value
164
- end
165
-
166
- def frame_body_class
167
- case @name
168
- when :comment
169
- CommentFrameBody
170
- when :genre
171
- GenreFrameBody
172
- when :image
173
- ImageFrameBody
174
- else
175
- TextFrameBody
176
- end
177
- end
178
- end
179
- end
180
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class FrameBody
6
- # Textual frames are marked with an encoding byte.
7
- #
8
- # $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00.
9
- # $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM.
10
- # $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
11
- # $03 UTF-8 [UTF-8] encoded Unicode [UNICODE].
12
- ENCODING_MAPPING = %w(ISO-8859-1 UTF-16 UTF-16BE UTF-8)
13
-
14
- ENCODING_TERMINATOR_SIZE = {
15
- 'ISO-8859-1' => 1,
16
- 'UTF-16' => 2,
17
- 'UTF-16BE' => 2,
18
- 'UTF-8' => 1
19
- }
20
-
21
-
22
- attr_reader :value
23
-
24
- def initialize(content, version)
25
- @content = content
26
- @version = version
27
-
28
- parse
29
- end
30
-
31
- def parse
32
- raise WahWahNotImplementedError, 'The parse method is not implemented'
33
- end
34
- end
35
- end
36
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class GenreFrameBody < TextFrameBody
6
- def parse
7
- super
8
-
9
- # If value is numeric value, or contain numeric value in parens
10
- # can use as index for ID3v1 genre list
11
- @value = ID3::V1::GENRES[$1.to_i] if @value =~ /^\((\d+)\)$/ || @value =~ /^(\d+)$/
12
- end
13
- end
14
- end
15
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class ImageFrameBody < FrameBody
6
- TYPES = %i(
7
- other
8
- file_icon
9
- other_file_icon
10
- cover_front
11
- cover_back
12
- leaflet
13
- media
14
- lead_artist
15
- artist
16
- conductor
17
- band
18
- composer
19
- lyricist
20
- recording_location
21
- during_recording
22
- during_performance
23
- movie_screen_capture
24
- bright_coloured_fish
25
- illustration
26
- band_logotype
27
- publisher_logotype
28
- )
29
-
30
- def mime_type
31
- mime_type = @mime_type.downcase.yield_self { |type| type == 'jpg' ? 'jpeg' : type }
32
- @version > 2 ? mime_type : "image/#{mime_type}"
33
- end
34
-
35
- # ID3v2.2 image frame structure:
36
- #
37
- # Text encoding $xx
38
- # Image format $xx xx xx
39
- # Picture type $xx
40
- # Description <text string according to encoding> $00 (00)
41
- # Picture data <binary data>
42
- #
43
- # ID3v2.3 and ID3v2.4 image frame structure:
44
- #
45
- # Text encoding $xx
46
- # MIME type <text string> $00
47
- # Picture type $xx
48
- # Description <text string according to encoding> $00 (00)
49
- # Picture data <binary data>
50
- def parse
51
- frame_format = @version > 2 ? 'CZ*Ca*' : 'Ca3Ca*'
52
- encoding_id, @mime_type, type_index, reset_content = @content.unpack(frame_format)
53
- encoding = ENCODING_MAPPING[encoding_id]
54
- _description, data = Helper.split_with_terminator(reset_content, ENCODING_TERMINATOR_SIZE[encoding])
55
-
56
- @value = { data: data, mime_type: mime_type, type: TYPES[type_index] }
57
- end
58
- end
59
- end
60
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class TextFrameBody < FrameBody
6
- # Text frame boby structure:
7
- #
8
- # Text encoding $xx
9
- # Information <text string according to encoding>
10
- def parse
11
- encoding_id, text = @content.unpack('Ca*')
12
- @value = Helper.encode_to_utf8(text, source_encoding: ENCODING_MAPPING[encoding_id])
13
- end
14
- end
15
- end
16
- end
data/lib/wahwah/id3/v1.rb DELETED
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WahWah
4
- module ID3
5
- class V1 < Tag
6
- TAG_SIZE = 128
7
- TAG_ID = 'TAG'
8
- DEFAULT_ENCODING = 'iso-8859-1'
9
- GENRES = [
10
- # Standard Genres
11
- 'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge',
12
- 'Hip-Hop', 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop',
13
- 'R&B', 'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative',
14
- 'Ska', 'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno', 'Ambient', 'Trip-Hop',
15
- 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', 'Classical', 'Instrumental', 'Acid',
16
- 'House', 'Game', 'Sound Clip', 'Gospel', 'Noise', 'AlternRock', 'Bass',
17
- 'Soul', 'Punk', 'Space', 'Meditative', 'Instrumental Pop', 'Instrumental Rock', 'Ethnic',
18
- 'Gothic', 'Darkwave', 'Techno-Industrial', 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream',
19
- 'Southern Rock', 'Comedy', 'Cult', 'Gangsta', 'Top 40', 'Christian Rap', 'Pop/Funk',
20
- 'Jungle', 'Native American', 'Cabaret', 'New Wave', 'Psychadelic', 'Rave', 'Showtunes',
21
- 'Trailer', 'Lo-Fi', 'Tribal', 'Acid Punk', 'Acid Jazz', 'Polka', 'Retro',
22
- 'Musical', 'Rock & Roll', 'Hard Rock',
23
-
24
- # Winamp Extended Genres
25
- 'Folk', 'Folk-Rock', 'National Folk', 'Swing', 'Fast Fusion', 'Bebob', 'Latin',
26
- 'Revival', 'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock',
27
- 'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening', 'Acoustic', 'Humour',
28
- 'Speech', 'Chanson', 'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass',
29
- 'Primus', 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba',
30
- 'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet', 'Punk Rock',
31
- 'Drum Solo', 'A capella', 'Euro-House', 'Dance Hall', 'Goa', 'Drum & Bass', 'Club-House',
32
- 'Hardcore Techno', 'Terror', 'Indie', 'BritPop', 'Negerpunk', 'Polsk Punk', 'Beat',
33
- 'Christian Gangsta Rap', 'Heavy Metal', 'Black Metal', 'Contemporary Christian', 'Christian Rock',
34
-
35
- # Added on WinAmp 1.91
36
- 'Merengue', 'Salsa', 'Thrash Metal', 'Anime', 'Jpop', 'Synthpop',
37
-
38
- # Added on WinAmp 5.6
39
- 'Abstract', 'Art Rock', 'Baroque', 'Bhangra', 'Big Beat', 'Breakbeat', 'Chillout',
40
- 'Downtempo', 'Dub', 'EBM', 'Eclectic', 'Electro', 'Electroclash', 'Emo',
41
- 'Experimental', 'Garage', 'Illbient', 'Industro-Goth', 'Jam Band', 'Krautrock', 'Leftfield',
42
- 'Lounge', 'Math Rock', 'New Romantic', 'Nu-Breakz', 'Post-Punk', 'Post-Rock', 'Psytrance',
43
- 'Shoegaze', 'Space Rock', 'Trop Rock', 'World Music', 'Neoclassical', 'Audiobook', 'Audio Theatre',
44
- 'Neue Deutsche Welle', 'Podcast', 'Indie Rock', 'G-Funk', 'Dubstep', 'Garage Rock', 'Psybient'
45
- ]
46
-
47
- def size
48
- TAG_SIZE
49
- end
50
-
51
- def version
52
- 'v1'
53
- end
54
-
55
- def valid?
56
- @id == TAG_ID
57
- end
58
-
59
- private
60
- # For ID3v1 info, see here https://en.wikipedia.org/wiki/ID3#ID3v1
61
- #
62
- # header 3 "TAG"
63
- # title 30 30 characters of the title
64
- # artist 30 30 characters of the artist name
65
- # album 30 30 characters of the album name
66
- # year 4 A four-digit year
67
- # comment 28 or 30 The comment.
68
- # zero-byte 1 If a track number is stored, this byte contains a binary 0.
69
- # track 1 The number of the track on the album, or 0. Invalid, if previous byte is not a binary 0.
70
- # genre 1 Index in a list of genres, or 255
71
- def parse
72
- return unless @file_io.size >= TAG_SIZE
73
-
74
- @file_io.seek(-TAG_SIZE, IO::SEEK_END)
75
- @id = Helper.encode_to_utf8(@file_io.read(3), source_encoding: DEFAULT_ENCODING)
76
-
77
- return unless valid?
78
-
79
- @title = Helper.encode_to_utf8(@file_io.read(30), source_encoding: DEFAULT_ENCODING)
80
- @artist = Helper.encode_to_utf8(@file_io.read(30), source_encoding: DEFAULT_ENCODING)
81
- @album = Helper.encode_to_utf8(@file_io.read(30), source_encoding: DEFAULT_ENCODING)
82
- @year = Helper.encode_to_utf8(@file_io.read(4), source_encoding: DEFAULT_ENCODING)
83
-
84
- comment = @file_io.read(30)
85
-
86
- if comment.getbyte(-2) == 0
87
- @track = comment.getbyte(-1)
88
- comment = comment.byteslice(0..-3)
89
- end
90
-
91
- @comments.push(Helper.encode_to_utf8(comment, source_encoding: DEFAULT_ENCODING))
92
- @genre = GENRES[@file_io.getbyte] || ''
93
- end
94
- end
95
- end
96
- end