Class: ID3Lib::Tag
Overview
This class is the main frontend of the library. Use it to read and write ID3 tag data of files.
Example of use
tag = ID3Lib::Tag.new('shy_boy.mp3')
# Remove comments
tag.delete_if{ |frame| frame[:id] == :COMM }
# Set year
tag.year #=> 2000
tag.year = 2005
# Apply changes
tag.update!
Working with tags
You can use a ID3Lib::Tag object like an array. In fact, it is a subclass of Array. An ID3Lib::Tag contains frames which are stored as hashes, with field IDs as keys and field values as values. The frame IDs like TIT2 are the ones specified by the ID3 standard. If you don’t know these IDs, you probably want to use the accessor methods described afterwards, which have a more natural naming.
tag.each do |frame|
p frame
end
#=> {:id => :TIT2, :text => "Shy Boy", :textenc => 0}
#=> {:id => :TPE1, :text => "Katie Melua", :textenc => 0}
#=> {:id => :TALB, :text => "Piece By Piece", :textenc => 0}
#=> {:id => :TRCK, :text => "1/12", :textenc => 0}
#=> {:id => :TYER, :text => "2005", :textenc => 0}
#=> {:id => :TCON, :text => "Jazz/Blues", :textenc => 0}
Get and set frames
There are a number of accessors for text frames like title, performer, album, track, year, comment and genre. Have a look at ID3Lib::Accessors for a complete list. They can only be used for text that is encoded with ISO-8859-1.
tag.title #=> "Shy Boi"
tag.title = 'Shy Boy'
tag.title #=> "Shy Boy"
tag.track #=> [1,12]
tag.year #=> 2005
You can always read and write the raw text if you want. You just have to use the “manual access”. It is generally encouraged to use the #frame_text method where possible, because the other two result in an exception when the frame isn’t found.
tag.frame_text(:TRCK) #=> "1/12"
tag.frame_text(:TLAN) #=> nil
tag.frame(:TRCK)[:text] #=> "1/12"
# Raises an exception, because nil[:text] isn't possible:
tag.frame(:TLAN)[:text]
tag.find{ |f| f[:id] == :TRCK }[:text] #=> "1/12"
# Also raises an exception:
tag.find{ |f| f[:id] == :TLAN }[:text]
Because only ISO-8859-1 encoded text frames can be set with accessors, you have to add special frames by hand.
# Add two comments
tag << {:id => :COMM, :text => 'chunky bacon'}
tag << {:id => :COMM, :text => 'really.'}
# Add an UTF-16 text frame with BOM (byte order mark)
tag << {:id => :TIT2, :text => "\xff\xfe\x60\x4f\x7d\x59",
:textenc => 1}
# Add an attached picture
cover = {
:id => :APIC,
:mimetype => 'image/jpeg',
:picturetype => 3,
:description => 'A pretty picture',
:textenc => 0,
:data => File.read('cover.jpg')
}
tag << cover
Get information about frames
In the last example we added an APIC frame. How can we know what data we have to store in the APIC hash?
ID3Lib::Info.frame(:APIC)[3]
#=> [:textenc, :mimetype, :picturetype, :description, :data]
We see, the last element of the info array obtained through ID3Lib::Info.frame is an array of field IDs needed by APIC.
Have a look at the ID3Lib::Info module for detailed information.
Write changes to file
When you’ve finished modifying a tag, don’t forget to call #update! to write the modifications back to the file. You have to check the return value of update!, it returns nil on failure. This probably means that the file is not writeable or cannot be created.
tag.update!
Getting rid of a tag
Use the #strip! method to completely remove a tag from a file.
tag.strip!
Instance Attribute Summary collapse
-
#padding ⇒ Object
Returns the value of attribute padding.
Instance Method Summary collapse
-
#frame(id) ⇒ Object
Simple shortcut for getting a frame by its id.
-
#frame_text(id) ⇒ Object
Get the text of a frame specified by id.
-
#has_tag?(type = V2) ⇒ Boolean
Check if there is a tag of type type.
-
#initialize(filename, readtype = V_ALL) ⇒ Tag
constructor
Create a new Tag.
-
#invalid_frames ⇒ Object
Returns an Array of invalid frames and fields.
-
#remove_frame(id) ⇒ Object
Remove all frames with the specified id.
-
#set_frame_text(id, text) ⇒ Object
Set the text of a frame.
-
#size ⇒ Object
Returns an estimate of the number of bytes required to store the tag data.
-
#strip!(striptype = V_ALL) ⇒ Object
Strip tag from file.
-
#update!(writetype = @readtype) ⇒ Object
Updates the tag.
-
#user_frame_text(description) ⇒ Object
Get the text of a user frame specified by description.
Methods included from Accessors
#album, #album=, #band, #band=, #bpm, #bpm=, #comment, #comment=, #comment_frames, #composer, #composer=, #conductor, #conductor=, #date, #date=, #encoded_by, #encoded_by=, #genre, #genre=, #grouping, #grouping=, #interpreted_by, #interpreted_by=, #language, #language=, #lyricist, #lyricist=, #lyrics, #lyrics=, #part_of_set, #part_of_set=, #performer, #performer=, #publisher, #publisher=, #subtitle, #subtitle=, #time, #time=, #title, #title=, #track, #track=, #year, #year=
Constructor Details
#initialize(filename, readtype = V_ALL) ⇒ Tag
Create a new Tag. When a filename is supplied, the tag of the file is read. tagtype specifies the tag type to read and defaults to V_ALL. Use one of ID3Lib::V1, ID3Lib::V2, ID3Lib::V_BOTH or ID3Lib::V_ALL.
tag = ID3Lib::Tag.new('shy_boy.mp3')
Only read ID3v1 tag:
id3v1_tag = ID3Lib::Tag.new('piece_by_piece.mp3', ID3Lib::V1)
167 168 169 170 171 172 173 174 175 |
# File 'lib/id3lib.rb', line 167 def initialize(filename, readtype=V_ALL) @filename = filename @readtype = readtype @padding = true @tag = API::Tag.new @tag.link(@filename, @readtype) read_frames end |
Instance Attribute Details
#padding ⇒ Object
Returns the value of attribute padding.
153 154 155 |
# File 'lib/id3lib.rb', line 153 def padding @padding end |
Instance Method Details
#frame(id) ⇒ Object
Simple shortcut for getting a frame by its id.
tag.frame(:TIT2)
#=> {:id => :TIT2, :text => "Shy Boy", :textenc => 0}
is the same as:
tag.find{ |f| f[:id] == :TIT2 }
195 196 197 |
# File 'lib/id3lib.rb', line 195 def frame(id) find{ |f| f[:id] == id } end |
#frame_text(id) ⇒ Object
Get the text of a frame specified by id. Returns nil if the frame can’t be found.
tag.find{ |f| f[:id] == :TIT2 }[:text] #=> "Shy Boy"
tag.frame_text(:TIT2) #=> "Shy Boy"
tag.find{ |f| f[:id] == :TLAN } #=> nil
tag.frame_text(:TLAN) #=> nil
209 210 211 212 |
# File 'lib/id3lib.rb', line 209 def frame_text(id) f = frame(id) f ? f[:text] : nil end |
#has_tag?(type = V2) ⇒ Boolean
Check if there is a tag of type type.
302 303 304 305 |
# File 'lib/id3lib.rb', line 302 def has_tag?(type=V2) @tag.link(@filename, V_ALL) @tag.has_tag_type(type) end |
#invalid_frames ⇒ Object
Returns an Array of invalid frames and fields. If a frame ID is invalid, it alone is in the resulting array. If a frame ID is valid but has invalid fields, the frame ID and the invalid field IDs are included.
tag.invalid_frames
#=> [ [:TITS], [:TALB, :invalid] ]
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/id3lib.rb', line 316 def invalid_frames invalid = [] each do |frame| if not info = Info.frame(frame[:id]) # Frame ID doesn't exist. invalid << [frame[:id]] next end # Frame ID is ok, but are all fields ok? invalid_fields = frame.keys.reject { |id| info[FIELDS].include?(id) or id == :id } if not invalid_fields.empty? invalid << [frame[:id], *invalid_fields] end end invalid.empty? ? nil : invalid end |
#remove_frame(id) ⇒ Object
Remove all frames with the specified id.
245 246 247 |
# File 'lib/id3lib.rb', line 245 def remove_frame(id) delete_if{ |f| f[:id] == id } end |
#set_frame_text(id, text) ⇒ Object
Set the text of a frame. First, all frames with the specified id are deleted and then a new frame with text is appended.
tag.set_frame_text(:TLAN, 'eng')
235 236 237 238 239 240 |
# File 'lib/id3lib.rb', line 235 def set_frame_text(id, text) remove_frame(id) if text self << { :id => id, :text => text.to_s } end end |
#size ⇒ Object
Returns an estimate of the number of bytes required to store the tag data.
181 182 183 |
# File 'lib/id3lib.rb', line 181 def size @tag.size end |
#strip!(striptype = V_ALL) ⇒ Object
291 292 293 294 295 296 297 |
# File 'lib/id3lib.rb', line 291 def strip!(striptype=V_ALL) clear = @tag.strip(striptype) @tag.clear @tag.link(@filename, @readtype) end |
#update!(writetype = @readtype) ⇒ Object
Updates the tag. This change can’t be undone. writetype specifies which tag type to write and defaults to readtype (see #new).
Invalid frames or frame data is ignored. Use #invalid_frames before update! if you want to know if you have invalid data.
Returns a number corresponding to the written tag type(s) or nil if the update failed.
tag.update!
id3v1_tag.update!(ID3Lib::V1)
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/id3lib.rb', line 262 def update!(writetype=@readtype) @tag.strip(writetype) # The following two lines are necessary because of the weird # behaviour of id3lib. @tag.clear @tag.link(@filename, writetype) delete_if do |frame| frame_info = Info.frame(frame[:id]) next true if not frame_info libframe = API::Frame.new(frame_info[NUM]) Frame.write(frame, libframe) @tag.add_frame(libframe) false end @tag.set_padding(@padding) = @tag.update(writetype) return == 0 ? nil : end |
#user_frame_text(description) ⇒ Object
Get the text of a user frame specified by description. Returns nil if the frame can’t be found.
tag.user_frame_text('MusicBrainz Album Id')
#=> "f0d6c31f-8f9f-47fe-b5f5-3b96746b48fa"
tag.user_frame_text('MusicBrainz Album Artist Id')
#=> nil
224 225 226 227 |
# File 'lib/id3lib.rb', line 224 def user_frame_text(description) f = find{ |f| f[:id] == :TXXX && f[:description] == description } f ? f[:text] : nil end |