Coverage Report - org.jaudiotagger.tag.id3.ID3v11Tag
 
Classes in this File Line Coverage Branch Coverage Complexity
ID3v11Tag
65%
132/201
61%
58/94
3.24
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: ID3v11Tag.java 836 2009-11-12 15:44:07Z paultaylor $
 6  
  *
 7  
  *  MusicTag Copyright (C)2003,2004
 8  
  *
 9  
  *  This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
 10  
  *  General Public  License as published by the Free Software Foundation; either version 2.1 of the License,
 11  
  *  or (at your option) any later version.
 12  
  *
 13  
  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 14  
  *  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 15  
  *  See the GNU Lesser General Public License for more details.
 16  
  *
 17  
  *  You should have received a copy of the GNU Lesser General Public License along with this library; if not,
 18  
  *  you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software
 19  
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20  
  *
 21  
  * Description:
 22  
  * This class is for a ID3v1.1 Tag
 23  
  *
 24  
  */
 25  
 package org.jaudiotagger.tag.id3;
 26  
 
 27  
 import org.jaudiotagger.audio.generic.Utils;
 28  
 import org.jaudiotagger.audio.mp3.MP3File;
 29  
 import org.jaudiotagger.logging.ErrorMessage;
 30  
 import org.jaudiotagger.tag.*;
 31  
 import org.jaudiotagger.tag.id3.framebody.*;
 32  
 
 33  
 import java.io.IOException;
 34  
 import java.io.RandomAccessFile;
 35  
 import java.nio.ByteBuffer;
 36  
 import java.nio.channels.FileChannel;
 37  
 import java.util.ArrayList;
 38  
 import java.util.Arrays;
 39  
 import java.util.Iterator;
 40  
 import java.util.List;
 41  
 import java.util.logging.Level;
 42  
 import java.util.regex.Matcher;
 43  
 
 44  
 /**
 45  
  * Represents an ID3v11 tag.
 46  
  *
 47  
  * @author : Eric Farng
 48  
  * @author : Paul Taylor
 49  
  */
 50  
 public class ID3v11Tag extends ID3v1Tag
 51  
 {
 52  
 
 53  
     //For writing output
 54  
     protected static final String TYPE_TRACK = "track";
 55  
 
 56  
     protected static final int TRACK_UNDEFINED = 0;
 57  
     protected static final int TRACK_MAX_VALUE = 255;
 58  
     protected static final int TRACK_MIN_VALUE = 1;
 59  
 
 60  
     protected static final int FIELD_COMMENT_LENGTH = 28;
 61  
     protected static final int FIELD_COMMENT_POS = 97;
 62  
 
 63  
     protected static final int FIELD_TRACK_INDICATOR_LENGTH = 1;
 64  
     protected static final int FIELD_TRACK_INDICATOR_POS = 125;
 65  
 
 66  
     protected static final int FIELD_TRACK_LENGTH = 1;
 67  
     protected static final int FIELD_TRACK_POS = 126;
 68  
 
 69  
     /**
 70  
      * Track is held as a single byte in v1.1
 71  
      */
 72  2109
     protected byte track = (byte) TRACK_UNDEFINED;
 73  
 
 74  
     private static final byte RELEASE = 1;
 75  
     private static final byte MAJOR_VERSION = 1;
 76  
     private static final byte REVISION = 0;
 77  
 
 78  
     /**
 79  
      * Retrieve the Release
 80  
      */
 81  
     public byte getRelease()
 82  
     {
 83  16
         return RELEASE;
 84  
     }
 85  
 
 86  
     /**
 87  
      * Retrieve the Major Version
 88  
      */
 89  
     public byte getMajorVersion()
 90  
     {
 91  16
         return MAJOR_VERSION;
 92  
     }
 93  
 
 94  
     /**
 95  
      * Retrieve the Revision
 96  
      */
 97  
     public byte getRevision()
 98  
     {
 99  16
         return REVISION;
 100  
     }
 101  
 
 102  
     /**
 103  
      * Creates a new ID3v11 datatype.
 104  
      */
 105  
     public ID3v11Tag()
 106  40
     {
 107  
 
 108  40
     }
 109  
 
 110  
     public int getFieldCount()
 111  
     {
 112  0
         return 7;
 113  
     }
 114  
 
 115  
     public ID3v11Tag(ID3v11Tag copyObject)
 116  
     {
 117  0
         super(copyObject);
 118  0
         this.track = copyObject.track;
 119  0
     }
 120  
 
 121  
     /**
 122  
      * Creates a new ID3v11 datatype from a non v11 tag
 123  
      *
 124  
      * @param mp3tag
 125  
      * @throws UnsupportedOperationException
 126  
      */
 127  
     public ID3v11Tag(AbstractTag mp3tag)
 128  24
     {
 129  24
         if (mp3tag != null)
 130  
         {
 131  24
             if (mp3tag instanceof ID3v1Tag)
 132  
             {
 133  0
                 if (mp3tag instanceof ID3v11Tag)
 134  
                 {
 135  0
                     throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
 136  
                 }
 137  
                 // id3v1_1 objects are also id3v1 objects
 138  0
                 ID3v1Tag id3old = (ID3v1Tag) mp3tag;
 139  0
                 this.title = id3old.title;
 140  0
                 this.artist = id3old.artist;
 141  0
                 this.album = id3old.album;
 142  0
                 this.comment = id3old.comment;
 143  0
                 this.year = id3old.year;
 144  0
                 this.genre = id3old.genre;
 145  0
             }
 146  
             else
 147  
             {
 148  
                 ID3v24Tag id3tag;
 149  
                 // first change the tag to ID3v2_4 tag if not one already
 150  24
                 if (!(mp3tag instanceof ID3v24Tag))
 151  
                 {
 152  16
                     id3tag = new ID3v24Tag(mp3tag);
 153  
                 }
 154  
                 else
 155  
                 {
 156  8
                     id3tag = (ID3v24Tag) mp3tag;
 157  
                 }
 158  
                 ID3v24Frame frame;
 159  
                 String text;
 160  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_TITLE))
 161  
                 {
 162  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_TITLE);
 163  0
                     text = ((FrameBodyTIT2) frame.getBody()).getText();
 164  0
                     this.title = ID3Tags.truncate(text, FIELD_TITLE_LENGTH);
 165  
                 }
 166  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_ARTIST))
 167  
                 {
 168  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_ARTIST);
 169  0
                     text = ((FrameBodyTPE1) frame.getBody()).getText();
 170  0
                     this.artist = ID3Tags.truncate(text, FIELD_ARTIST_LENGTH);
 171  
                 }
 172  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_ALBUM))
 173  
                 {
 174  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_ALBUM);
 175  0
                     text = ((FrameBodyTALB) frame.getBody()).getText();
 176  0
                     this.album = ID3Tags.truncate(text, FIELD_ALBUM_LENGTH);
 177  
                 }
 178  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_YEAR))
 179  
                 {
 180  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_YEAR);
 181  0
                     text = ((FrameBodyTDRC) frame.getBody()).getText();
 182  0
                     this.year = ID3Tags.truncate(text, FIELD_YEAR_LENGTH);
 183  
                 }
 184  
 
 185  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_COMMENT))
 186  
                 {
 187  0
                     Iterator iterator = id3tag.getFrameOfType(ID3v24Frames.FRAME_ID_COMMENT);
 188  0
                     text = "";
 189  0
                     while (iterator.hasNext())
 190  
                     {
 191  0
                         frame = (ID3v24Frame) iterator.next();
 192  0
                         text += (((FrameBodyCOMM) frame.getBody()).getText() + " ");
 193  
                     }
 194  0
                     this.comment = ID3Tags.truncate(text, FIELD_COMMENT_LENGTH);
 195  
                 }
 196  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_GENRE))
 197  
                 {
 198  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_GENRE);
 199  0
                     text = ((FrameBodyTCON) frame.getBody()).getText();
 200  
                     try
 201  
                     {
 202  0
                         this.genre = (byte) ID3Tags.findNumber(text);
 203  
                     }
 204  0
                     catch (TagException ex)
 205  
                     {
 206  0
                         logger.log(Level.WARNING, getLoggingFilename() + ":" + "Unable to convert TCON frame to format suitable for v11 tag", ex);
 207  0
                         this.genre = (byte) ID3v1Tag.GENRE_UNDEFINED;
 208  0
                     }
 209  
                 }
 210  24
                 if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_TRACK))
 211  
                 {
 212  0
                     frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_TRACK);
 213  0
                     this.track = (byte) ((FrameBodyTRCK) frame.getBody()).getTrackNo().intValue();
 214  
                 }
 215  
             }
 216  
         }
 217  24
     }
 218  
 
 219  
     /**
 220  
      * Creates a new ID3v11 datatype.
 221  
      *
 222  
      * @param file
 223  
      * @param loggingFilename
 224  
      * @throws TagNotFoundException
 225  
      * @throws IOException
 226  
      */
 227  
     public ID3v11Tag(RandomAccessFile file, String loggingFilename) throws TagNotFoundException, IOException
 228  2045
     {
 229  2045
         setLoggingFilename(loggingFilename);
 230  
         FileChannel fc;
 231  2045
         ByteBuffer byteBuffer = ByteBuffer.allocate(TAG_LENGTH);
 232  
 
 233  2045
         fc = file.getChannel();
 234  2045
         fc.position(file.length() - TAG_LENGTH);
 235  
 
 236  2045
         fc.read(byteBuffer);
 237  2045
         byteBuffer.flip();
 238  2045
         read(byteBuffer);
 239  
 
 240  33
     }
 241  
 
 242  
     /**
 243  
      * Creates a new ID3v11 datatype.
 244  
      *
 245  
      * @param file
 246  
      * @throws TagNotFoundException
 247  
      * @throws IOException
 248  
      * @deprecated use {@link #ID3v11Tag(RandomAccessFile,String)} instead
 249  
      */
 250  
     public ID3v11Tag(RandomAccessFile file) throws TagNotFoundException, IOException
 251  
     {
 252  0
         this(file, "");
 253  
 
 254  0
     }
 255  
 
 256  
     /**
 257  
      * Set Comment
 258  
      *
 259  
      * @param comment
 260  
      */
 261  
     public void setComment(String comment)
 262  
     {
 263  36
         if (comment == null)
 264  
         {
 265  4
             throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
 266  
         }
 267  32
         this.comment = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH);
 268  32
     }
 269  
 
 270  
     /**
 271  
      * Get Comment
 272  
      *
 273  
      * @return comment
 274  
      */
 275  
     public String getFirstComment()
 276  
     {
 277  48
         return comment;
 278  
     }
 279  
 
 280  
     /**
 281  
      * Set the track, v11 stores track numbers in a single byte value so can only
 282  
      * handle a simple number in the range 0-255.
 283  
      *
 284  
      * @param trackValue
 285  
      */
 286  
     
 287  
     public void setTrack(String trackValue)
 288  
     {
 289  
         int trackAsInt;
 290  
         //Try and convert String representation of track into an integer
 291  
         try
 292  
         {
 293  28
             trackAsInt = Integer.parseInt(trackValue);
 294  
         }
 295  0
         catch (NumberFormatException e)
 296  
         {
 297  0
             trackAsInt = 0;
 298  28
         }
 299  
 
 300  
         //This value cannot be held in v1_1
 301  28
         if ((trackAsInt > TRACK_MAX_VALUE) || (trackAsInt < TRACK_MIN_VALUE))
 302  
         {
 303  0
             this.track = (byte) TRACK_UNDEFINED;
 304  
         }
 305  
         else
 306  
         {
 307  28
             this.track = (byte) Integer.parseInt(trackValue);
 308  
         }
 309  28
     }
 310  
 
 311  
     /**
 312  
      * Return the track number as a String.
 313  
      *
 314  
      * @return track
 315  
      */
 316  
 
 317  
     public String getFirstTrack()
 318  
     {
 319  48
         return String.valueOf(track & BYTE_TO_UNSIGNED);
 320  
     }
 321  
 
 322  
     public void addTrack(String track)
 323  
     {
 324  0
         setTrack(track);
 325  0
     }
 326  
 
 327  
     public List<TagField> getTrack()
 328  
     {
 329  16
         if (getFirst(FieldKey.TRACK).length() > 0)
 330  
         {
 331  16
             ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.TRACK.name(), getFirst(FieldKey.TRACK));
 332  16
             return returnFieldToList(field);
 333  
         }
 334  
         else
 335  
         {
 336  0
             return new ArrayList<TagField>();
 337  
         }
 338  
     }
 339  
 
 340  
     public void setField(TagField field)
 341  
     {
 342  88
         FieldKey genericKey = FieldKey.valueOf(field.getId());
 343  88
         if (genericKey == FieldKey.TRACK)
 344  
         {
 345  8
             setTrack(field.toString());
 346  
         }
 347  
         else
 348  
         {
 349  80
             super.setField(field);
 350  
         }
 351  84
     }
 352  
 
 353  
     public List<TagField> getFields(FieldKey genericKey)
 354  
     {
 355  32
         if (genericKey == FieldKey.TRACK)
 356  
         {
 357  4
             return getTrack();
 358  
         }
 359  
         else
 360  
         {
 361  28
             return super.getFields(genericKey);
 362  
         }
 363  
     }
 364  
 
 365  
     public TagField getFirstField(String id)
 366  
     {
 367  
         List<TagField> results;
 368  
 
 369  28
         if (FieldKey.TRACK.name().equals(id))
 370  
         {
 371  4
             results = getTrack();
 372  4
             if (results != null)
 373  
             {
 374  4
                 if (results.size() > 0)
 375  
                 {
 376  4
                     return results.get(0);
 377  
                 }
 378  
             }
 379  0
             return null;
 380  
         }
 381  
         else
 382  
         {
 383  24
             return super.getFirstField(id);
 384  
         }
 385  
     }
 386  
 
 387  
     public boolean isEmpty()
 388  
     {
 389  12
         return track <= 0 && super.isEmpty();
 390  
     }
 391  
 
 392  
     /**
 393  
      * Delete any instance of tag fields with this key
 394  
      *
 395  
      * @param genericKey
 396  
      */
 397  
     public void deleteField(FieldKey genericKey)
 398  
     {
 399  32
         if (genericKey == FieldKey.TRACK)
 400  
         {
 401  4
             track = 0;
 402  
         }
 403  
         else
 404  
         {
 405  28
             super.deleteField(genericKey);
 406  
         }
 407  32
     }
 408  
 
 409  
     /**
 410  
      * Compares Object with this only returns true if both v1_1 tags with all
 411  
      * fields set to same value
 412  
      *
 413  
      * @param obj Comparing Object
 414  
      * @return
 415  
      */
 416  
     public boolean equals(Object obj)
 417  
     {
 418  0
         if (!(obj instanceof ID3v11Tag))
 419  
         {
 420  0
             return false;
 421  
         }
 422  0
         ID3v11Tag object = (ID3v11Tag) obj;
 423  0
         return this.track == object.track && super.equals(obj);
 424  
     }
 425  
 
 426  
 
 427  
     /**
 428  
      * Find identifer within byteBuffer to indicate that a v11 tag exists within the buffer
 429  
      *
 430  
      * @param byteBuffer
 431  
      * @return true if find header for v11 tag within buffer
 432  
      */
 433  
     public boolean seek(ByteBuffer byteBuffer)
 434  
     {
 435  2079
         byte[] buffer = new byte[FIELD_TAGID_LENGTH];
 436  
         // read the TAG value
 437  2079
         byteBuffer.get(buffer, 0, FIELD_TAGID_LENGTH);
 438  2079
         if (!(Arrays.equals(buffer, TAG_ID)))
 439  
         {
 440  1750
             return false;
 441  
         }
 442  
 
 443  
         // Check for the empty byte before the TRACK
 444  329
         byteBuffer.position(FIELD_TRACK_INDICATOR_POS);
 445  329
         if (byteBuffer.get() != END_OF_FIELD)
 446  
         {
 447  6
             return false;
 448  
         }
 449  
         //Now check for TRACK if the next byte is also null byte then not v1.1
 450  
         //tag, however this means cannot have v1_1 tag with track setField to zero/undefined
 451  
         //because on next read will be v1 tag.
 452  323
         return byteBuffer.get() != END_OF_FIELD;
 453  
     }
 454  
 
 455  
     /**
 456  
      * Read in a tag from the ByteBuffer
 457  
      *
 458  
      * @param byteBuffer from where to read in a tag
 459  
      * @throws TagNotFoundException if unable to read a tag in the byteBuffer
 460  
      */
 461  
     public void read(ByteBuffer byteBuffer) throws TagNotFoundException
 462  
     {
 463  2045
         if (!seek(byteBuffer))
 464  
         {
 465  2012
             throw new TagNotFoundException("ID3v1 tag not found");
 466  
         }
 467  33
         logger.finer("Reading v1.1 tag");
 468  
 
 469  
         //Do single file read of data to cut down on file reads
 470  33
         byte[] dataBuffer = new byte[TAG_LENGTH];
 471  33
         byteBuffer.position(0);
 472  33
         byteBuffer.get(dataBuffer, 0, TAG_LENGTH);
 473  33
         title = Utils.getString(dataBuffer, FIELD_TITLE_POS, FIELD_TITLE_LENGTH, "ISO-8859-1").trim();
 474  33
         Matcher m = AbstractID3v1Tag.endofStringPattern.matcher(title);
 475  33
         if (m.find())
 476  
         {
 477  0
             title = title.substring(0, m.start());
 478  
         }
 479  33
         artist = Utils.getString(dataBuffer, FIELD_ARTIST_POS, FIELD_ARTIST_LENGTH, "ISO-8859-1").trim();
 480  33
         m = AbstractID3v1Tag.endofStringPattern.matcher(artist);
 481  33
         if (m.find())
 482  
         {
 483  0
             artist = artist.substring(0, m.start());
 484  
         }
 485  33
         album = Utils.getString(dataBuffer, FIELD_ALBUM_POS, FIELD_ALBUM_LENGTH, "ISO-8859-1").trim();
 486  33
         m = AbstractID3v1Tag.endofStringPattern.matcher(album);
 487  33
         if (m.find())
 488  
         {
 489  0
             album = album.substring(0, m.start());
 490  
         }
 491  33
         year = Utils.getString(dataBuffer, FIELD_YEAR_POS, FIELD_YEAR_LENGTH, "ISO-8859-1").trim();
 492  33
         m = AbstractID3v1Tag.endofStringPattern.matcher(year);
 493  33
         if (m.find())
 494  
         {
 495  0
             year = year.substring(0, m.start());
 496  
         }
 497  33
         comment = Utils.getString(dataBuffer, FIELD_COMMENT_POS, FIELD_COMMENT_LENGTH, "ISO-8859-1").trim();
 498  33
         m = AbstractID3v1Tag.endofStringPattern.matcher(comment);
 499  33
         if (m.find())
 500  
         {
 501  0
             comment = comment.substring(0, m.start());
 502  
         }
 503  33
         track = dataBuffer[FIELD_TRACK_POS];
 504  33
         genre = dataBuffer[FIELD_GENRE_POS];
 505  33
     }
 506  
 
 507  
 
 508  
     /**
 509  
      * Write this representation of tag to the file indicated
 510  
      *
 511  
      * @param file that this tag should be written to
 512  
      * @throws IOException thrown if there were problems writing to the file
 513  
      */
 514  
     public void write(RandomAccessFile file) throws IOException
 515  
     {
 516  34
         logger.info("Saving ID3v11 tag to file");
 517  34
         byte[] buffer = new byte[TAG_LENGTH];
 518  
         int i;
 519  
         String str;
 520  34
         delete(file);
 521  34
         file.seek(file.length());
 522  34
         System.arraycopy(TAG_ID, FIELD_TAGID_POS, buffer, FIELD_TAGID_POS, TAG_ID.length);
 523  34
         int offset = FIELD_TITLE_POS;
 524  34
         if (TagOptionSingleton.getInstance().isId3v1SaveTitle())
 525  
         {
 526  34
             str = ID3Tags.truncate(title, FIELD_TITLE_LENGTH);
 527  121
             for (i = 0; i < str.length(); i++)
 528  
             {
 529  87
                 buffer[i + offset] = (byte) str.charAt(i);
 530  
             }
 531  
         }
 532  34
         offset = FIELD_ARTIST_POS;
 533  34
         if (TagOptionSingleton.getInstance().isId3v1SaveArtist())
 534  
         {
 535  34
             str = ID3Tags.truncate(artist, FIELD_ARTIST_LENGTH);
 536  305
             for (i = 0; i < str.length(); i++)
 537  
             {
 538  271
                 buffer[i + offset] = (byte) str.charAt(i);
 539  
             }
 540  
         }
 541  34
         offset = FIELD_ALBUM_POS;
 542  34
         if (TagOptionSingleton.getInstance().isId3v1SaveAlbum())
 543  
         {
 544  34
             str = ID3Tags.truncate(album, FIELD_ALBUM_LENGTH);
 545  297
             for (i = 0; i < str.length(); i++)
 546  
             {
 547  263
                 buffer[i + offset] = (byte) str.charAt(i);
 548  
             }
 549  
         }
 550  34
         offset = FIELD_YEAR_POS;
 551  34
         if (TagOptionSingleton.getInstance().isId3v1SaveYear())
 552  
         {
 553  34
             str = ID3Tags.truncate(year, FIELD_YEAR_LENGTH);
 554  58
             for (i = 0; i < str.length(); i++)
 555  
             {
 556  24
                 buffer[i + offset] = (byte) str.charAt(i);
 557  
             }
 558  
         }
 559  34
         offset = FIELD_COMMENT_POS;
 560  34
         if (TagOptionSingleton.getInstance().isId3v1SaveComment())
 561  
         {
 562  34
             str = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH);
 563  62
             for (i = 0; i < str.length(); i++)
 564  
             {
 565  28
                 buffer[i + offset] = (byte) str.charAt(i);
 566  
             }
 567  
         }
 568  34
         offset = FIELD_TRACK_POS;
 569  34
         buffer[offset] = track; // skip one byte extra blank for 1.1 definition
 570  34
         offset = FIELD_GENRE_POS;
 571  34
         if (TagOptionSingleton.getInstance().isId3v1SaveGenre())
 572  
         {
 573  34
             buffer[offset] = genre;
 574  
         }
 575  34
         file.write(buffer);
 576  
 
 577  34
         logger.info("Saved ID3v11 tag to file");
 578  34
     }
 579  
 
 580  
 
 581  
     public void createStructure()
 582  
     {
 583  0
         MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier());
 584  
         //Header
 585  0
         MP3File.getStructureFormatter().addElement(TYPE_TITLE, this.title);
 586  0
         MP3File.getStructureFormatter().addElement(TYPE_ARTIST, this.artist);
 587  0
         MP3File.getStructureFormatter().addElement(TYPE_ALBUM, this.album);
 588  0
         MP3File.getStructureFormatter().addElement(TYPE_YEAR, this.year);
 589  0
         MP3File.getStructureFormatter().addElement(TYPE_COMMENT, this.comment);
 590  0
         MP3File.getStructureFormatter().addElement(TYPE_TRACK, this.track);
 591  0
         MP3File.getStructureFormatter().addElement(TYPE_GENRE, this.genre);
 592  0
         MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG);
 593  
 
 594  0
     }
 595  
 }