Class: ID3Lib::Tag

Class | ID3Lib::Tag
In: | lib/id3lib.rb
Parent: | Array

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.

       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 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 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!

### Methods

frame frame_text has_tag? invalid_frames new remove_frame set_frame_text size strip! update!

### Included Modules

Accessors

### Attributes

padding | [RW] |

### Public Class methods

new(filename, readtype=V_ALL)

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)

[Source]

         # File lib/id3lib.rb, line 162
    162:     def initialize(filename, readtype=V_ALL)
    163:       @filename = filename
    164:       @readtype = readtype
    165:       @padding = true
    166:
    167:       @tag = API::Tag.new
    168:       @tag.link(@filename, @readtype)
    169:       read_frames
    170:     end

### Public Instance methods

frame(id)

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 }

[Source]

         # File lib/id3lib.rb, line 190
    190:     def frame(id)
    191:       find{ |f| f[:id] == id }
    192:     end

frame_text(id)

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

[Source]

         # File lib/id3lib.rb, line 204
    204:     def frame_text(id)
    205:       f = frame(id)
    206:       f ? f[:text] : nil
    207:     end

has_tag?(type=V2)

Check if there is a tag of type type.

[Source]

         # File lib/id3lib.rb, line 282
    282:     def has_tag?(type=V2)
    283:       @tag.link(@filename, V_ALL)
    284:       @tag.has_tag_type(type)
    285:     end

invalid_frames()

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] ]

[Source]

         # File lib/id3lib.rb, line 296
    296:     def invalid_frames
    297:       invalid = []
    298:       each do |frame|
    299:         if not info = Info.frame(frame[:id])
    300:           # Frame ID doesn't exist.
    301:           invalid << [frame[:id]]
    302:           next
    303:         end
    304:         # Frame ID is ok, but are all fields ok?
    305:         invalid_fields = frame.keys.reject { |id|
    306:           info[FIELDS].include?(id) or id == :id
    307:         }
    308:         if not invalid_fields.empty?
    309:           invalid << [frame[:id], *invalid_fields]
    310:         end
    311:       end
    312:       invalid.empty? ? nil : invalid
    313:     end

remove_frame(id)

Remove all frames with the specified id.

[Source]

         # File lib/id3lib.rb, line 225
    225:     def remove_frame(id)
    226:       delete_if{ |f| f[:id] == id }
    227:     end

set_frame_text(id, text)

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')

[Source]

         # File lib/id3lib.rb, line 215
    215:     def set_frame_text(id, text)
    216:       remove_frame(id)
    217:       if text
    218:         self << { :id => id, :text => text.to_s }
    219:       end
    220:     end

size()

Returns an estimate of the number of bytes required to store the tag data.

[Source]

         # File lib/id3lib.rb, line 176
    176:     def size
    177:       @tag.size
    178:     end

strip!(striptype=V_ALL)

Strip tag from file. This is dangerous because you lose all tag information. Specify striptag to only strip a certain tag type. You don‘t have to call update! after strip!.

       tag.strip!
       another_tag.strip!(ID3Lib::V1)

[Source]

         # File lib/id3lib.rb, line 271
    271:     def strip!(striptype=V_ALL)
    272:       clear
    273:       tags = @tag.strip(striptype)
    274:       @tag.clear
    275:       @tag.link(@filename, @readtype)
    276:       tags
    277:     end

update!(writetype=@readtype)

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)

[Source]

         # File lib/id3lib.rb, line 242
    242:     def update!(writetype=@readtype)
    243:       @tag.strip(writetype)
    244:       # The following two lines are necessary because of the weird
    245:       # behaviour of id3lib.
    246:       @tag.clear
    247:       @tag.link(@filename, writetype)
    248:
    249:       delete_if do |frame|
    250:         frame_info = Info.frame(frame[:id])
    251:         next true if not frame_info
    252:         libframe = API::Frame.new(frame_info[NUM])
    253:         Frame.write(frame, libframe)
    254:         @tag.add_frame(libframe)
    255:         false
    256:       end
    257:
    258:       @tag.set_padding(@padding)
    259:       tags = @tag.update(writetype)
    260:       return tags == 0 ? nil : tags
    261:     end

[Validate]