wahwah 0.1.0.pre.test → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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