Class: ID3

Inherits:
Object
  • Object
show all
Defined in:
lib/lctr_mp3.rb

Overview

This class represents the data held in an ID3 tag attached to an .mp3 music file. It is intended to be a container

for the fields that are listed in attr_accessor and included in the file "id_frame_ids.rb" that should be held in the
same directory.  Upon calling the class with the name of an .mp3 file, the initialize method should pull all of the 
required data into the instance.  This data can later be modified and exported to a tag.

This currently works only for ID3 tags version 2.3.

ID3 technical information taken from http://id3.org/id3v2.3.0.

Author:: Neil Woodward
License::  MIT

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ ID3

This will read in all of the tag data when the instance is initialized.



23
24
25
26
27
28
29
30
31
# File 'lib/lctr_mp3.rb', line 23

def initialize(file)
	@file = file
	header = get_tag_header 
	tag_size = parse_header(header)
	tag = get_tag(tag_size)
	get_frames(tag)
	set_file
	set_flag(header[5])
end

Instance Attribute Details

#album_titleObject

Returns the value of attribute album_title.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def album_title
  @album_title
end

#artistObject

Returns the value of attribute artist.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def artist
  @artist
end

#flagsObject

Returns the value of attribute flags.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def flags
  @flags
end

#mp3_fileObject

Returns the value of attribute mp3_file.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def mp3_file
  @mp3_file
end

#pathObject

Returns the value of attribute path.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def path
  @path
end

#song_titleObject

Returns the value of attribute song_title.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def song_title
  @song_title
end

#timeObject

Returns the value of attribute time.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def time
  @time
end

#trackObject

Returns the value of attribute track.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def track
  @track
end

#versionObject

Returns the value of attribute version.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def version
  @version
end

#yearObject

Returns the value of attribute year.



20
21
22
# File 'lib/lctr_mp3.rb', line 20

def year
  @year
end

Instance Method Details

#check_ID3(header) ⇒ Object

This method verifies the header is indeed an ID3 header.



75
76
77
78
79
# File 'lib/lctr_mp3.rb', line 75

def check_ID3(header)
	unless header[0..2].join == "ID3"
		raise "No ID3 tag on the file"
	end
end

#check_ver(header) ⇒ Object

This method ensures that we have the correct ID3 version.



82
83
84
85
86
87
88
# File 'lib/lctr_mp3.rb', line 82

def check_ver(header)
	if header[3..4].join(' ') == "\x03 \x00"
		@version = "2.3"
	else
		raise "Incorrect ID3 version - require v2.3"
	end
end

#get_frames(tag) ⇒ Object

This method is used to search the tag for the desired frame tags, and identify the frame locations and sizes.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/lctr_mp3.rb', line 96

def get_frames(tag)
  FRAMES.keys.each do |type|

    if loc = (/#{type}/ =~ tag)
      fr_size_arr = tag[loc+4,4].bytes
      fr_size_str=""

      fr_size_arr.each do |ch|
      	fr_size_str<<ch.to_s(2).rjust(8,"0")
      end

      fr_size = fr_size_str.to_i(2)
      #p fr_size
      frm = tag[loc+10,fr_size] .gsub(/^\u0000+/,'')
      #p frm

      eval("self.#{FRAMES[type]} = frm")

   	else
  		eval("self.#{FRAMES[type]} = nil")
  	end

  end

end

#get_tag(size) ⇒ Object

This will read the tag into memory and assign to the “tag” variable for later scraping.



56
57
58
59
60
61
62
63
64
65
# File 'lib/lctr_mp3.rb', line 56

def get_tag(size)
	tag = ""
	File.open(@file, "r") do |f|
		f.each_byte.with_index do |ch,index|
			tag << ch

		  return tag if index > size
	  end
	end
end

#get_tag_headerObject

This reads the first 10 bytes of the tag, which contain the metadata of the tag.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/lctr_mp3.rb', line 34

def get_tag_header
	header = Array.new
	File.open(@file, "r") do |f|
		f.each_byte.with_index do |ch, index|
			case index
			when 0..4
		    header << ch.chr
		  when 5
		  	header << ch.to_s(2)[0..2]
		  when 6..9
		  	if ch > 128
		  		raise "Header error:  reported tag size too large"
		  	end
		  	header << ch.to_s(2).rjust(7,"0")
		  end
		  return header if index > 10
		end
	end

end

#parse_header(header) ⇒ Object

This is the method that will parse the ID3 header, making sure that it is actually a good ID3 header.



68
69
70
71
72
# File 'lib/lctr_mp3.rb', line 68

def parse_header(header)
 	check_ID3(header)
 	check_ver(header)
 	return tag_size(header[6..9])
end

#set_fileObject

Used to set the file name.



123
124
125
126
# File 'lib/lctr_mp3.rb', line 123

def set_file
	@path = File.dirname(@file)
	@mp3_file = File.basename(@file)
end

#set_flag(flags) ⇒ Object

Used to set the flag bits.



129
130
131
# File 'lib/lctr_mp3.rb', line 129

def set_flag(flags)
	@flags = flags
end

#tag_size(header6_9) ⇒ Object

This method converts the size bytes in the header into a decimal number representation of the header size.



91
92
93
# File 'lib/lctr_mp3.rb', line 91

def tag_size(header6_9)
	header6_9.join.to_i(2)
end