id3 1.0.0.pre5 → 1.0.0.pre6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Rakefile +2 -0
- data/examples/id3_statistics_with_Audiofile.rb +115 -0
- data/examples/mp3/example_mp3_file_with_id3v2_2_0.mp3 +0 -0
- data/examples/mp3/rheeeeet.mp3 +0 -0
- data/examples/old/example2.rb +134 -0
- data/examples/old/examples.rb +165 -0
- data/examples/old/id3statistics.rb +145 -0
- data/examples/read_remote_id3v2_tag.rb +74 -0
- data/id3.gemspec +33 -0
- data/lib/id3.rb +1 -0
- data/lib/id3/constants.rb +1 -1
- data/lib/id3/version.rb +3 -0
- metadata +48 -36
data/.gitignore
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
|
2
|
+
require 'awesome_print'
|
3
|
+
|
4
|
+
require 'id3'
|
5
|
+
|
6
|
+
|
7
|
+
require '../lib/helpers/recursive_helper'
|
8
|
+
|
9
|
+
|
10
|
+
# ------------------------------------------------------------------------------
|
11
|
+
def each_song(filename)
|
12
|
+
filename.chomp!
|
13
|
+
@mp3fileN += 1
|
14
|
+
|
15
|
+
# puts "Filename: #{filename}"
|
16
|
+
|
17
|
+
if File.size(filename) == 0
|
18
|
+
@empty_fileN += 1
|
19
|
+
puts "EMPTY MP3-File: #{filename}" # better to know this, hum?
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
mp3 = AudioFile.new(filename) # CAN WE CALL THIS WITH A BLOCK??
|
24
|
+
if mp3.id3_versions.empty?
|
25
|
+
@no_id3_tagN += 1
|
26
|
+
puts "NO ID3 TAGS: #{filename}" # better to know this, hum?
|
27
|
+
return
|
28
|
+
else
|
29
|
+
mp3.id3_versions.each do |v|
|
30
|
+
# count how often we saw a certain ID3 tag version
|
31
|
+
@id3_versionNH[v] += 1
|
32
|
+
|
33
|
+
if mp3.has_id3v2tag?
|
34
|
+
# count how often we saw a certain ID3v2 tag size
|
35
|
+
@id3v2_tag_sizesH[v][mp3.tagID3v2.raw.size] ||= 0
|
36
|
+
@id3v2_tag_sizesH[v][mp3.tagID3v2.raw.size] += 1
|
37
|
+
|
38
|
+
# count how often we saw a certain ID3v2 tag
|
39
|
+
mp3.tagID3v2.keys.each do |tag|
|
40
|
+
@id3v2_fields_usedH[v][tag] ||= 0
|
41
|
+
@id3v2_fields_usedH[v][tag] += 1
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@only_id3v1_tagN += 1 # if a file only has a ID3v1 tag, we also need a warning message
|
45
|
+
puts "ONLY ID3v1 TAG: #{filename}" # better to know this, hum?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# ------------------------------------------------------------------------------
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
mp3_library_dir = File.join( ENV['HOME'] , 'Music/iTunes/iTunes Music') # e.g. on a Mac
|
55
|
+
|
56
|
+
@dirN = 0
|
57
|
+
@fileN = 0
|
58
|
+
@mp3fileN = 0
|
59
|
+
|
60
|
+
@empty_fileN = 0
|
61
|
+
@no_id3_tagN = 0
|
62
|
+
@only_id3v1_tagN = 0
|
63
|
+
|
64
|
+
@id3v2_fields_usedH = {}
|
65
|
+
@id3v2_tag_sizesH = {}
|
66
|
+
@id3_versionNH = {}
|
67
|
+
ID3::VERSIONS.each do |v|
|
68
|
+
@id3v2_fields_usedH[v] = {}
|
69
|
+
@id3v2_tag_sizesH[v] = {}
|
70
|
+
@id3_versionNH[v] = 0
|
71
|
+
end
|
72
|
+
|
73
|
+
# gather statistics on the ID3 tags used in your MP3 library:
|
74
|
+
recursive_dir_descend( mp3_library_dir , /.*.[mM][pP]3$/ , 'each_song(filename)'); 1
|
75
|
+
|
76
|
+
|
77
|
+
print "
|
78
|
+
Files checked: #{@fileN}
|
79
|
+
Dirs checked: #{@dirN}
|
80
|
+
|
81
|
+
MP3 Files found: #{@mp3fileN}
|
82
|
+
|
83
|
+
Empty MP3 Files: #{@empty_fileN}
|
84
|
+
|
85
|
+
NO ID3 Tag at all: #{@no_id3_tagN}
|
86
|
+
|
87
|
+
ONLY ID3v2 Tag: #{@only_id3v1_tagN}
|
88
|
+
|
89
|
+
"
|
90
|
+
|
91
|
+
puts '--------------------'
|
92
|
+
ap @id3v2_fields_usedH ; 1
|
93
|
+
puts '--------------------'
|
94
|
+
ap @id3v2_tag_sizesH ;1
|
95
|
+
puts '--------------------'
|
96
|
+
ap @id3_versionNH ;1
|
97
|
+
puts '--------------------'
|
98
|
+
|
99
|
+
print "
|
100
|
+
Files checked: #{@fileN}
|
101
|
+
Dirs checked: #{@dirN}
|
102
|
+
|
103
|
+
MP3 Files found: #{@mp3fileN}
|
104
|
+
|
105
|
+
Empty MP3 Files: #{@empty_fileN}
|
106
|
+
|
107
|
+
NO ID3 Tag at all: #{@no_id3_tagN}
|
108
|
+
|
109
|
+
ONLY ID3v2 Tag: #{@only_id3v1_tagN}
|
110
|
+
|
111
|
+
"
|
112
|
+
|
113
|
+
puts "\n\ndone."
|
114
|
+
|
115
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
require 'id3'
|
3
|
+
|
4
|
+
tag1 = ID3::Tag1.new
|
5
|
+
tag1.read('mp3/d.mp3')
|
6
|
+
|
7
|
+
tag2 = ID3::Tag1.new
|
8
|
+
tag2.read('mp3/a.mp3')
|
9
|
+
|
10
|
+
raw = tag1.dump
|
11
|
+
raw.hexdump
|
12
|
+
tag1.raw.hexdump
|
13
|
+
|
14
|
+
t = ID3::Tag1.new
|
15
|
+
v,h = t.parse!(raw)
|
16
|
+
|
17
|
+
|
18
|
+
raw = tag2.dump
|
19
|
+
raw.hexdump
|
20
|
+
v,h = t.parse!(raw)
|
21
|
+
|
22
|
+
|
23
|
+
t['BLA'] = "blubb"
|
24
|
+
|
25
|
+
# --------------------------------------------------------------------------------
|
26
|
+
|
27
|
+
require 'id3'
|
28
|
+
|
29
|
+
t = ID3::Tag2.new
|
30
|
+
t.read("mp3/d.mp3")
|
31
|
+
t["ARTIST"]
|
32
|
+
|
33
|
+
t["ARTIST"].dump.hexdump
|
34
|
+
|
35
|
+
t.delete('PICTURE')
|
36
|
+
t.dump.hexdump
|
37
|
+
|
38
|
+
# --------------------------------------------------------------------------------
|
39
|
+
|
40
|
+
require 'id3'
|
41
|
+
|
42
|
+
a = ID3::AudioFile.new("mp3/a.mp3")
|
43
|
+
t1 = a.write
|
44
|
+
a1 = a.writeAudio
|
45
|
+
|
46
|
+
aa = ID3::AudioFile.new( t1 )
|
47
|
+
t2 = aa.write
|
48
|
+
a2 = aa.writeAudio
|
49
|
+
|
50
|
+
aaa = ID3::AudioFile.new( t2 )
|
51
|
+
t3 = aaa.write
|
52
|
+
a3 = aaa.writeAudio
|
53
|
+
|
54
|
+
a.audioLength
|
55
|
+
aa.audioLength
|
56
|
+
aaa.audioLength
|
57
|
+
|
58
|
+
` ls -l t1 t2 t3`
|
59
|
+
|
60
|
+
# to create a test file
|
61
|
+
|
62
|
+
File.open("mp3/test.mp3", "w+") { |f|
|
63
|
+
256.times { |i|
|
64
|
+
f.putc i
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
# --------------------------------------------------------------------------------
|
69
|
+
|
70
|
+
|
71
|
+
require 'id3'
|
72
|
+
|
73
|
+
a = ID3::AudioFile.new("mp3/a.mp3")
|
74
|
+
b = ID3::AudioFile.new("mp3/b.mp3")
|
75
|
+
c = ID3::AudioFile.new("mp3/c.mp3")
|
76
|
+
d = ID3::AudioFile.new("mp3/d.mp3")
|
77
|
+
e = ID3::AudioFile.new("mp3/reeeee.mp3")
|
78
|
+
a = ID3::AudioFile.new("mp3/King_Crimson_-_Three_of_a_Perfect_Pair_-_06_-_Industry.mp3")
|
79
|
+
|
80
|
+
d.tagID3v2["TMEDIATYPE"].flags
|
81
|
+
|
82
|
+
d.tagID3v2.version
|
83
|
+
d.tagID3v2["ARTIST"].rawflags
|
84
|
+
d.tagID3v2["ARTIST"].flags
|
85
|
+
|
86
|
+
d.tagID3v2["ARTIST"].raw
|
87
|
+
d.tagID3v2["ARTIST"].rawheader
|
88
|
+
d.tagID3v2["ARTIST"].rawdata
|
89
|
+
|
90
|
+
|
91
|
+
t = ID3::Tag2.new
|
92
|
+
t.read("mp3/b.mp3")
|
93
|
+
|
94
|
+
t["COMMENT"]
|
95
|
+
t["COMMENT"].order
|
96
|
+
|
97
|
+
t["COMMENT"]["bla"] =3
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
t['COMMENT'].rawdata.hexdump
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
t2["SONGLEN"].rawdata.hexdump
|
106
|
+
t2["SONGLEN"].dump.hexdump
|
107
|
+
|
108
|
+
|
109
|
+
# to check which symbols don't have a matching pack/unpack pattern:
|
110
|
+
|
111
|
+
(ID3::Framename2symbol["2.2.0"].values +
|
112
|
+
ID3::Framename2symbol["2.3.0"].values +
|
113
|
+
ID3::Framename2symbol["2.4.0"].values).uniq.each { |symbol|
|
114
|
+
print "SYMBOL: #{symbol} not defined!\n" if ! ID3::FrameName2FrameType[symbol]
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
ID3::FrameName2FrameType["ARTIST"]
|
120
|
+
ID3::FrameName2FrameType
|
121
|
+
|
122
|
+
|
123
|
+
t2["ARTIST"].raw
|
124
|
+
|
125
|
+
t2["ARTIST"].rawdata
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
t1 = ID3::Tag2.new
|
131
|
+
t1.read("mp3/b.mp3")
|
132
|
+
t1["ARTIST"]
|
133
|
+
|
134
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
# ------------------------------------------------------------------------------
|
3
|
+
# SOME EXAMPLES on how the library is intended to be used
|
4
|
+
# ------------------------------------------------------------------------------
|
5
|
+
|
6
|
+
# EXAMPLE of stripping extra v1-tag if v2-tag is present:
|
7
|
+
|
8
|
+
file = "bla.mp3"
|
9
|
+
if ID3::has_id3_tag?( file )
|
10
|
+
myfile = AudioFile.open( file ) # do we need a new here?
|
11
|
+
|
12
|
+
# if a file has both tags (v1 and v2), we delete the v1 tag:
|
13
|
+
if (myfile.has_id3v1_tag?) && (myfile.has_id3v2_tag?)
|
14
|
+
myfile.id3v1tag = nil
|
15
|
+
myfile.write # we only write if we modified it..
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# NOTE: may use id3v1tag.clear or id3v1tag = {} instead
|
20
|
+
|
21
|
+
# ------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
# EXAMPLE of stripping attached pictures from id3v2-tags if present,
|
24
|
+
# and re-setting the play counter to 0
|
25
|
+
# and setting the comment to something silly
|
26
|
+
|
27
|
+
file = "bla.mp3"
|
28
|
+
if ID3::has_id3v2_tag?( file )
|
29
|
+
myfile = AudioFile.open( file ) # do we need a new here?
|
30
|
+
# if (myfile.id3v2tag.member?(PICTURE)) # if there is a picture in the tag..
|
31
|
+
myfile.id3v2tag.delete(PICTURE) # deletes the unwanted picture..
|
32
|
+
# end
|
33
|
+
myfile.id3v2tag["PLAYCOUNTER"] = 0 # reset the play counter to 0
|
34
|
+
myfile.id3v2tag["COMMENT"] = "Tilo's MP3 collection" # set the comment
|
35
|
+
|
36
|
+
myfile.id3v2tag.options["PADDINGSIZE"] = 0 # shrink the tag!
|
37
|
+
myfile.id3v2tag.options["APPENDTAG"] = false # shrink the tag!
|
38
|
+
myfile.id3v2tag.options["FOOTER"] = false # shrink the tag!
|
39
|
+
myfile.id3v2tag.options["EXT_HEADER"] = false # shrink the tag!
|
40
|
+
|
41
|
+
myfile.write # writes to the same filename, overwriting the old file
|
42
|
+
myfile.write("new.mp3") # creates new file
|
43
|
+
myfile.close
|
44
|
+
end
|
45
|
+
|
46
|
+
# ------------------------------------------------------------------------------
|
47
|
+
|
48
|
+
# CODE FRAGMENT from initialization of AudioFile
|
49
|
+
|
50
|
+
# when we open a file and create a new ID3-tag, we should do this internally:
|
51
|
+
|
52
|
+
v1 = ID3::has_id3v1_tag?( file )
|
53
|
+
v2 = ID3::has_id3v2_tag?( file ) # but may not be a version we know
|
54
|
+
# about...
|
55
|
+
|
56
|
+
if (v2) # if version is not nil
|
57
|
+
id3v2tag = ID3v2tag.new( v2 ) # only create tag if one in file
|
58
|
+
end
|
59
|
+
|
60
|
+
if (v1)
|
61
|
+
id3v1tag = ID3v1tag.new( v1 ) # only create tag if one in file
|
62
|
+
end
|
63
|
+
|
64
|
+
# or we do it the same way as in the old library:
|
65
|
+
|
66
|
+
v1 = ID3::has_id3v1_tag?( file )
|
67
|
+
v2 = ID3::has_id3v2_tag?( file )
|
68
|
+
|
69
|
+
id3v2tag = ID3v2tag.new( v2 )
|
70
|
+
id3v2tag.read_v2(file)
|
71
|
+
|
72
|
+
|
73
|
+
# similarly, when creating a new frame, we need to read it first,
|
74
|
+
# before we can create the correct instance with the correct singleton
|
75
|
+
# methods...
|
76
|
+
|
77
|
+
frame = Frame.new # should create a new frame of the correct type..
|
78
|
+
|
79
|
+
# ------------------------------------------------------------------------------
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
------------------------------------------------------------------------------
|
86
|
+
|
87
|
+
# EXAMPLE tagging an existing MP3 track..
|
88
|
+
|
89
|
+
file = "/tmp/rheeeeet.mp3" # ./examples/mp3/rheeeeet.mp3
|
90
|
+
|
91
|
+
if ! ID3.hasID3v2tag?(file) # if there is no v2 tag
|
92
|
+
|
93
|
+
myfile = AudioFile.new( file ) # do we need a new here?
|
94
|
+
|
95
|
+
newtag = ID3::Tag2.new # create a new,empty v2 tag
|
96
|
+
newtag.version = '2.3.0'
|
97
|
+
newtag["TITLE"] = "Reeeeet!"
|
98
|
+
newtag["ARTIST"] = "Dan Mosedale"
|
99
|
+
newtag["LYRICIST"] = "Dan Mosedale"
|
100
|
+
newtag["COMPOSER"] = "Dan Mosedale"
|
101
|
+
newtag["LANGUAGE"] = "Monkey" # should raise an error, because there is no
|
102
|
+
# ISO language code for "Monkey"
|
103
|
+
|
104
|
+
newtag["BAND"] = "Mozilla and the ButtMonkeys"
|
105
|
+
newtag["TRACKNUM"] = '1' # will be converted to "1"
|
106
|
+
newtag["DATE"] = "2000/05/02" # will be converted to correct date format
|
107
|
+
|
108
|
+
newtag["COMMENT"] = "The sound which monkeys make when they are flying out of someones butt.. Which is refering to the estimated release date of Netscape 6. See: https://wiki.mozilla.org/SeaMonkey:Name_And_Version"
|
109
|
+
|
110
|
+
newtag.options["PADDINGSIZE"] = 0
|
111
|
+
|
112
|
+
myfile.tagID3v2 = newtag # assoziate the new tag with the AudioFile..
|
113
|
+
# NOTE: we should CHECK when assigning a tag,
|
114
|
+
# that the version number matches!
|
115
|
+
|
116
|
+
myfile.write # if we overwrite, we should save the old tag in "filename.oldtag"
|
117
|
+
myfile.close
|
118
|
+
end
|
119
|
+
------------------------------------------------------------------------------
|
120
|
+
|
121
|
+
# EXAMPLE to convert a file from older id3v2.x tags to id3v2.3 tags
|
122
|
+
|
123
|
+
file = "bla.mp3"
|
124
|
+
if ID3::has_id3v2_tag?( file )
|
125
|
+
myfile = AudioFile.open( file ) # do we need a new here?
|
126
|
+
|
127
|
+
if (myfile.id3v2tag.version < "2.3.0")
|
128
|
+
|
129
|
+
|
130
|
+
newtag = ID3v2tag("2.3.0")
|
131
|
+
|
132
|
+
# newtag = ID3v2tag.new # create new empty tag
|
133
|
+
# newtag.version = "2.3.0" # of specific version
|
134
|
+
|
135
|
+
myfile.id3v2tag.each { |key, value|
|
136
|
+
newtag[key] = value
|
137
|
+
}
|
138
|
+
myfile.id3v2tag = newtag
|
139
|
+
|
140
|
+
myfile.id3v2tag.options["PADDINGSIZE"] = 0 # shrink the tag!
|
141
|
+
|
142
|
+
myfile.write # writes to the same filename, overwriting the old file
|
143
|
+
myfile.write("new.mp3") # creates new file
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
myfile.close
|
148
|
+
end
|
149
|
+
|
150
|
+
------------------------------------------------------------------------------
|
151
|
+
|
152
|
+
# EXAMPLE to check if two tags are equivalent.. e.g. if they contain the
|
153
|
+
# same fields with the same values..
|
154
|
+
|
155
|
+
ID3::tags_equivalent(other)
|
156
|
+
|
157
|
+
# we also need to check if the number of keys is the same in each hash
|
158
|
+
|
159
|
+
equivalent = true
|
160
|
+
self.each { |key,value|
|
161
|
+
equivalent = false if self[key] != other[key]
|
162
|
+
}
|
163
|
+
return equivalent
|
164
|
+
|
165
|
+
------------------------------------------------------------------------------
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# this script collects statistical output about ID3 collection
|
4
|
+
#
|
5
|
+
|
6
|
+
require "id3"
|
7
|
+
|
8
|
+
|
9
|
+
# ------------------------------------------------------------------------------
|
10
|
+
# recursiveDirectoryDescend
|
11
|
+
# do action for files matching regexp
|
12
|
+
#
|
13
|
+
# could be extended to array of (regexp,action) pairs
|
14
|
+
#
|
15
|
+
def recursiveDirectoryDescend(dir,regexp,action)
|
16
|
+
# print "dir : #{dir}\n"
|
17
|
+
|
18
|
+
olddir = Dir.pwd
|
19
|
+
dirp = Dir.open(dir)
|
20
|
+
Dir.chdir(dir)
|
21
|
+
pwd = Dir.pwd
|
22
|
+
@@dirN += 1
|
23
|
+
|
24
|
+
for file in dirp
|
25
|
+
file.chomp
|
26
|
+
next if file =~ /^\.\.?$/
|
27
|
+
|
28
|
+
fullname = "#{pwd}/#{file}"
|
29
|
+
|
30
|
+
if File::directory?(fullname)
|
31
|
+
recursiveDirectoryDescend(fullname,regexp,action)
|
32
|
+
else
|
33
|
+
@@fileN += 1
|
34
|
+
if file =~ regexp
|
35
|
+
# evaluate action
|
36
|
+
eval action
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
Dir.chdir(olddir)
|
41
|
+
end
|
42
|
+
# ------------------------------------------------------------------------------
|
43
|
+
|
44
|
+
def eachSong(filename)
|
45
|
+
filename.chomp!
|
46
|
+
print "MP3-FILE: #{filename}"
|
47
|
+
@@mp3fileN += 1
|
48
|
+
|
49
|
+
if (File.size(filename) == 0)
|
50
|
+
puts " -- empty file\n"
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
v = 0
|
55
|
+
tagN = 0
|
56
|
+
|
57
|
+
v = ID3::hasID3v1tag?(filename)
|
58
|
+
if v
|
59
|
+
print " -- found ID3-tag version #{v}"
|
60
|
+
@@id3versionN[v] += 1
|
61
|
+
tagN += 1
|
62
|
+
end
|
63
|
+
|
64
|
+
v = ID3::hasID3v2tag?(filename)
|
65
|
+
if v
|
66
|
+
print " -- found ID3-tag version #{v}"
|
67
|
+
@@id3versionN[v] += 1
|
68
|
+
tagN += 1
|
69
|
+
|
70
|
+
tag2= ID3::Tag2.new
|
71
|
+
tag2.read(filename)
|
72
|
+
|
73
|
+
size = tag2.raw.size
|
74
|
+
@@sizeSum += size
|
75
|
+
@@sizeMax = size if size > @@sizeMax
|
76
|
+
printf "\ntag-size: %d , tag-keys: %s\n", size, tag2.keys.join(',')
|
77
|
+
|
78
|
+
|
79
|
+
tag2.keys.each { |field|
|
80
|
+
@@fieldsUsedN[tag2.version][field] += 1
|
81
|
+
}
|
82
|
+
end
|
83
|
+
if tagN == 0
|
84
|
+
print " -- no ID3-tag"
|
85
|
+
end
|
86
|
+
@@tagsPerFileN[tagN] += 1
|
87
|
+
puts "\n"
|
88
|
+
end
|
89
|
+
# ------------------------------------------------------------------------------
|
90
|
+
|
91
|
+
|
92
|
+
@@fileN = 0
|
93
|
+
@@mp3fileN = 0
|
94
|
+
@@dirN = 0
|
95
|
+
@@id3versionN = Hash.new(0)
|
96
|
+
|
97
|
+
@@fieldsUsedN = {}
|
98
|
+
ID3::VERSIONS.each do |v|
|
99
|
+
@@fieldsUsedN[v] ||= Hash.new(0)
|
100
|
+
end
|
101
|
+
|
102
|
+
@@sizeMax = 0
|
103
|
+
@@sizeSum = 0
|
104
|
+
|
105
|
+
|
106
|
+
@@tagsPerFileN= Array.new(3,0)
|
107
|
+
|
108
|
+
dir = ARGV[0]
|
109
|
+
|
110
|
+
recursiveDirectoryDescend(dir, /.*\.[mM][pP]3/, %q{ eachSong(fullname) } )
|
111
|
+
|
112
|
+
|
113
|
+
print "
|
114
|
+
|
115
|
+
Files checked : #{@@fileN}
|
116
|
+
Directories checked: #{@@dirN}
|
117
|
+
|
118
|
+
MP3 Files found : #{@@mp3fileN}
|
119
|
+
"
|
120
|
+
|
121
|
+
version2tagN = 0
|
122
|
+
|
123
|
+
@@id3versionN.keys.each { |v|
|
124
|
+
printf "\nnumber of ID3 tags v#{v} : #{@@id3versionN[v]}\n"
|
125
|
+
version2tagN += 1 if v =~ /^2\./
|
126
|
+
}
|
127
|
+
|
128
|
+
puts "\n"
|
129
|
+
|
130
|
+
@@tagsPerFileN.each_index{ |x|
|
131
|
+
printf "\nFiles tagged #{x}-times : #{@@tagsPerFileN[x]}\n"
|
132
|
+
}
|
133
|
+
|
134
|
+
ID3::SUPPORTED_SYMBOLS.keys.sort.each{ |v|
|
135
|
+
|
136
|
+
puts "\nFIELDS USED IN VERSION #{v}\n"
|
137
|
+
|
138
|
+
@@fieldsUsedN[v].keys.each { |field|
|
139
|
+
printf "\t%20s : %d\n", field, @@fieldsUsedN[v][field]
|
140
|
+
}
|
141
|
+
|
142
|
+
}
|
143
|
+
|
144
|
+
printf "\nMax v2 Tag Size was: %d , Average Tag Size was: %d\n" , @@sizeMax, (@@sizeSum / version2tagN)
|
145
|
+
puts "\n\ndone."
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- coding: undecided -*-
|
2
|
+
|
3
|
+
# See also: http://stackoverflow.com/questions/7656950/read-id3-tags-of-remote-mp3-file-in-ruby-rails
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'awesome_print' # debugging only
|
7
|
+
|
8
|
+
require 'net/http'
|
9
|
+
require 'uri'
|
10
|
+
require 'id3'
|
11
|
+
require 'hexdump' # debugging only
|
12
|
+
|
13
|
+
# --------------------------------------------------------------------------------------------
|
14
|
+
|
15
|
+
def get_remote_id3v2_tag( file_url )
|
16
|
+
id3v2_tag_size = get_remote_id3v2_tag_size( file_url )
|
17
|
+
if id3v2_tag_size > 0
|
18
|
+
buffer = get_remote_bytes(file_url, id3v2_tag_size )
|
19
|
+
tag2 = ID3::Tag2.new
|
20
|
+
tag2.read_from_buffer( buffer )
|
21
|
+
return tag2
|
22
|
+
else
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_remote_id3v2_tag_size( file_url )
|
28
|
+
buffer = get_remote_bytes( file_url, 100 )
|
29
|
+
if buffer.bytesize > 0
|
30
|
+
return buffer.ID3v2_tag_size
|
31
|
+
else
|
32
|
+
return 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_remote_bytes( file_url, n)
|
37
|
+
uri = URI(file_url)
|
38
|
+
size = n # ID3v2 tags can be considerably larger, because of embedded album pictures
|
39
|
+
Net::HTTP.version_1_2 # make sure we use higher HTTP protocol version than 1.0
|
40
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
41
|
+
resp = http.get( file_url , {'Range' => "bytes=0-#{size-1}"} )
|
42
|
+
resp_code = resp.code.to_i
|
43
|
+
if (resp_code >= 200 && resp_code < 300) then
|
44
|
+
return resp.body
|
45
|
+
else
|
46
|
+
return ''
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# --------------------------------------------------------------------------------------------
|
51
|
+
|
52
|
+
file_url = 'http://www.unixgods.org/~tilo/ID3/example_mp3_file_with_id3v2.mp3' # please specify a URL here for testing
|
53
|
+
|
54
|
+
|
55
|
+
puts "\nRemote File: \"#{file_url}\""
|
56
|
+
|
57
|
+
puts "\ncontains ID3v2 tag of size: #{get_remote_id3v2_tag_size( file_url )} Bytes"
|
58
|
+
|
59
|
+
tag2 = get_remote_id3v2_tag( file_url )
|
60
|
+
|
61
|
+
puts "\nID3v3 Version: #{tag2.version}\n"
|
62
|
+
|
63
|
+
puts "\ncontains Frames:\n"
|
64
|
+
ap tag2.keys
|
65
|
+
|
66
|
+
puts "\nID3v2 Tag:\n"
|
67
|
+
|
68
|
+
ap( tag2 )
|
69
|
+
|
70
|
+
puts "\nID3v2 Hexdump:\n"
|
71
|
+
|
72
|
+
puts tag2.raw.hexdump(true)
|
73
|
+
|
74
|
+
|
data/id3.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "id3/version"
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = 'id3'
|
7
|
+
s.version = ID3::VERSION
|
8
|
+
s.authors = ['Tilo Sloboda']
|
9
|
+
s.email = ['tilo.sloboda@gmail.com']
|
10
|
+
s.homepage = 'http://www.unixgods.org/~tilo/Ruby/ID3'
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.summary = 'A native ID3 tag library for Ruby, which does not depend on architecture-dependent C-libraries. It supports reading and writing ID3-tag versions 1.0, 1.1, and 2.2.x, 2,3.x, 2,4.x\n http://www.unixgods.org/~tilo/Ruby/ID3'
|
13
|
+
s.description = 'ID3 is a native ruby library for reading and writing ID3 tag versions 1.0, 1.1, and 2.2.x, 2,3.x, 2,4.x'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
# s.files = Dir['docs/**/*'] + Dir['lib/*.rb'] + Dir['lib/id3/*.rb'] + Dir['lib/helpers/*.rb'] + ['LICENSE.html' , 'index.html', 'README.md' , 'CHANGES']
|
17
|
+
# s.test_files = FileList["{tests}/**/*test.rb"].to_a
|
18
|
+
s.has_rdoc = false
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
s.autorequire = 'id3'
|
21
|
+
# s.extra_rdoc_files = ['README']
|
22
|
+
s.rdoc_options << '--title' << 'Native ID3 Ruby Library - uniform acecss to ID3v1 and ID3v2 tags'
|
23
|
+
s.add_dependency("activesupport", "~> 3.x")
|
24
|
+
# s.add_dependency("dependency", ">= 0.9.9")
|
25
|
+
# s.bindir = 'bin'
|
26
|
+
|
27
|
+
s.rubyforge_project = 'id3'
|
28
|
+
# s.rubyforge_project = ['none']
|
29
|
+
end
|
30
|
+
|
31
|
+
#Rake::GemPackageTask.new(spec) do |pkg|
|
32
|
+
# pkg.need_tar = true
|
33
|
+
#end
|
data/lib/id3.rb
CHANGED
@@ -14,6 +14,7 @@ require "helpers/hexdump" # only needed for debugging -> autoload
|
|
14
14
|
require 'id3/string_extensions' # adds ID3 methods to String
|
15
15
|
require 'id3/io_extensions' # adds ID3 methods to IO and File
|
16
16
|
|
17
|
+
require 'id3/version' # Gem Version
|
17
18
|
require 'id3/constants' # Constants used throughout the code
|
18
19
|
require 'id3/module_methods' # add ID3 methods to ID3 which operate on filenames
|
19
20
|
|
data/lib/id3/constants.rb
CHANGED
@@ -3,7 +3,7 @@ module ID3
|
|
3
3
|
# ----------------------------------------------------------------------------
|
4
4
|
# CONSTANTS
|
5
5
|
# ----------------------------------------------------------------------------
|
6
|
-
Version =
|
6
|
+
Version = VERSION
|
7
7
|
|
8
8
|
ID3v1tagSize = 128 # ID3v1 and ID3v1.1 have fixed size tags
|
9
9
|
ID3v1versionbyte = 125
|
data/lib/id3/version.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: id3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.pre6
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire: id3
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &5254080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,58 +21,70 @@ dependencies:
|
|
21
21
|
version: 3.x
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *5254080
|
25
25
|
description: ID3 is a native ruby library for reading and writing ID3 tag versions
|
26
26
|
1.0, 1.1, and 2.2.x, 2,3.x, 2,4.x
|
27
|
-
email:
|
27
|
+
email:
|
28
|
+
- tilo.sloboda@gmail.com
|
28
29
|
executables: []
|
29
30
|
extensions: []
|
30
31
|
extra_rdoc_files: []
|
31
32
|
files:
|
32
|
-
-
|
33
|
-
-
|
34
|
-
-
|
35
|
-
-
|
33
|
+
- .gitignore
|
34
|
+
- CHANGES
|
35
|
+
- LICENSE.html
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
36
38
|
- docs/Class_AudioFile.html
|
37
|
-
- docs/
|
38
|
-
- docs/
|
39
|
-
- docs/ID3_comparison2.html
|
39
|
+
- docs/Class_Frame.html
|
40
|
+
- docs/Class_Tag1.html
|
40
41
|
- docs/Class_Tag2.html
|
41
|
-
- docs/Module_ID3.html
|
42
|
-
- docs/id3.html
|
43
42
|
- docs/ID3-Standards/id3v2-00.html
|
43
|
+
- docs/ID3-Standards/id3v2-00.txt
|
44
|
+
- docs/ID3-Standards/id3v2.3.0.html
|
45
|
+
- docs/ID3-Standards/id3v2.3.0.txt
|
46
|
+
- docs/ID3-Standards/id3v2.4.0-changes.html
|
44
47
|
- docs/ID3-Standards/id3v2.4.0-changes.txt
|
45
48
|
- docs/ID3-Standards/id3v2.4.0-frames.html
|
46
|
-
- docs/ID3-Standards/id3v2.3.0.html
|
47
49
|
- docs/ID3-Standards/id3v2.4.0-frames.txt
|
48
|
-
- docs/ID3-Standards/id3v2.4.0-structure.txt
|
49
|
-
- docs/ID3-Standards/id3v2.4.0-changes.html
|
50
|
-
- docs/ID3-Standards/id3v2.3.0.txt
|
51
50
|
- docs/ID3-Standards/id3v2.4.0-structure.html
|
52
|
-
- docs/ID3-Standards/id3v2-
|
53
|
-
- docs/
|
51
|
+
- docs/ID3-Standards/id3v2.4.0-structure.txt
|
52
|
+
- docs/ID3_comparison.html
|
53
|
+
- docs/ID3_comparison2.html
|
54
|
+
- docs/ID3v2_frames_comparison.html
|
55
|
+
- docs/ID3v2_frames_overview.txt
|
56
|
+
- docs/Module_ID3.html
|
57
|
+
- docs/hexdump.rb
|
58
|
+
- docs/id3.html
|
59
|
+
- docs/index.html
|
60
|
+
- examples/id3_statistics_with_Audiofile.rb
|
61
|
+
- examples/mp3/example_mp3_file_with_id3v2_2_0.mp3
|
62
|
+
- examples/mp3/rheeeeet.mp3
|
63
|
+
- examples/old/example2.rb
|
64
|
+
- examples/old/examples.rb
|
65
|
+
- examples/old/id3statistics.rb
|
66
|
+
- examples/read_remote_id3v2_tag.rb
|
67
|
+
- id3.gemspec
|
68
|
+
- index.html
|
69
|
+
- lib/helpers/hash_extensions.rb
|
70
|
+
- lib/helpers/hexdump.rb
|
71
|
+
- lib/helpers/invert_hash.rb
|
72
|
+
- lib/helpers/recursive_helper.rb
|
73
|
+
- lib/helpers/restricted_ordered_hash.rb
|
74
|
+
- lib/helpers/ruby_1.8_1.9_compatibility.rb
|
54
75
|
- lib/id3.rb
|
55
|
-
- lib/id3/
|
56
|
-
- lib/id3/id3.rb
|
76
|
+
- lib/id3/audiofile.rb
|
57
77
|
- lib/id3/constants.rb
|
58
|
-
- lib/id3/tag2.rb
|
59
78
|
- lib/id3/frame.rb
|
79
|
+
- lib/id3/frame_array.rb
|
60
80
|
- lib/id3/generic_tag.rb
|
61
|
-
- lib/id3/
|
81
|
+
- lib/id3/id3.rb
|
62
82
|
- lib/id3/io_extensions.rb
|
63
|
-
- lib/id3/
|
64
|
-
- lib/id3/frame_array.rb
|
83
|
+
- lib/id3/module_methods.rb
|
65
84
|
- lib/id3/string_extensions.rb
|
66
|
-
- lib/
|
67
|
-
- lib/
|
68
|
-
- lib/
|
69
|
-
- lib/helpers/recursive_helper.rb
|
70
|
-
- lib/helpers/hash_extensions.rb
|
71
|
-
- lib/helpers/restricted_ordered_hash.rb
|
72
|
-
- LICENSE.html
|
73
|
-
- index.html
|
74
|
-
- README.md
|
75
|
-
- CHANGES
|
85
|
+
- lib/id3/tag1.rb
|
86
|
+
- lib/id3/tag2.rb
|
87
|
+
- lib/id3/version.rb
|
76
88
|
homepage: http://www.unixgods.org/~tilo/Ruby/ID3
|
77
89
|
licenses: []
|
78
90
|
post_install_message:
|