Coverage Report - org.jaudiotagger.tag.lyrics3.Lyrics3v2
 
Classes in this File Line Coverage Branch Coverage Complexity
Lyrics3v2
0%
0/142
0%
0/52
2.6
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: Lyrics3v2.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  
  */
 23  
 package org.jaudiotagger.tag.lyrics3;
 24  
 
 25  
 import org.jaudiotagger.tag.InvalidTagException;
 26  
 import org.jaudiotagger.tag.TagException;
 27  
 import org.jaudiotagger.tag.TagNotFoundException;
 28  
 import org.jaudiotagger.tag.TagOptionSingleton;
 29  
 import org.jaudiotagger.tag.id3.AbstractID3v2Frame;
 30  
 import org.jaudiotagger.tag.id3.AbstractTag;
 31  
 import org.jaudiotagger.tag.id3.ID3v1Tag;
 32  
 import org.jaudiotagger.tag.id3.ID3v24Tag;
 33  
 
 34  
 import java.io.IOException;
 35  
 import java.io.RandomAccessFile;
 36  
 import java.nio.ByteBuffer;
 37  
 import java.util.HashMap;
 38  
 import java.util.Iterator;
 39  
 
 40  
 public class Lyrics3v2 extends AbstractLyrics3
 41  
 {
 42  
     /**
 43  
      *
 44  
      */
 45  0
     private HashMap<String, Lyrics3v2Field> fieldMap = new HashMap<String, Lyrics3v2Field>();
 46  
 
 47  
     /**
 48  
      * Creates a new Lyrics3v2 datatype.
 49  
      */
 50  
     public Lyrics3v2()
 51  0
     {
 52  0
     }
 53  
 
 54  
     public Lyrics3v2(Lyrics3v2 copyObject)
 55  
     {
 56  0
         super(copyObject);
 57  
 
 58  0
         Iterator<String> iterator = copyObject.fieldMap.keySet().iterator();
 59  
         String oldIdentifier;
 60  
         String newIdentifier;
 61  
         Lyrics3v2Field newObject;
 62  
 
 63  0
         while (iterator.hasNext())
 64  
         {
 65  0
             oldIdentifier = iterator.next();
 66  0
             newIdentifier = oldIdentifier;
 67  0
             newObject = new Lyrics3v2Field(copyObject.fieldMap.get(newIdentifier));
 68  0
             fieldMap.put(newIdentifier, newObject);
 69  
         }
 70  0
     }
 71  
 
 72  
     /**
 73  
      * Creates a new Lyrics3v2 datatype.
 74  
      *
 75  
      * @param mp3tag
 76  
      * @throws UnsupportedOperationException
 77  
      */
 78  
     public Lyrics3v2(AbstractTag mp3tag)
 79  0
     {
 80  0
         if (mp3tag != null)
 81  
         {
 82  
             // upgrade the tag to lyrics3v2
 83  0
             if (mp3tag instanceof Lyrics3v2)
 84  
             {
 85  0
                 throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
 86  
             }
 87  0
             else if (mp3tag instanceof Lyrics3v1)
 88  
             {
 89  0
                 Lyrics3v1 lyricOld = (Lyrics3v1) mp3tag;
 90  
                 Lyrics3v2Field newField;
 91  0
                 newField = new Lyrics3v2Field(new FieldFrameBodyLYR(lyricOld.getLyric()));
 92  0
                 fieldMap.put(newField.getIdentifier(), newField);
 93  0
             }
 94  
             else
 95  
             {
 96  
                 Lyrics3v2Field newField;
 97  
                 Iterator<AbstractID3v2Frame> iterator;
 98  0
                 iterator = (new ID3v24Tag(mp3tag)).iterator();
 99  
 
 100  0
                 while (iterator.hasNext())
 101  
                 {
 102  
                     try
 103  
                     {
 104  0
                         newField = new Lyrics3v2Field(iterator.next());
 105  
 
 106  0
                         if (newField != null)
 107  
                         {
 108  0
                             fieldMap.put(newField.getIdentifier(), newField);
 109  
                         }
 110  
                     }
 111  0
                     catch (TagException ex)
 112  
                     {
 113  
                         //invalid frame to createField lyrics3 field. ignore and keep going
 114  0
                     }
 115  
                 }
 116  
             }
 117  
         }
 118  0
     }
 119  
 
 120  
     /**
 121  
      * Creates a new Lyrics3v2 datatype.
 122  
      *
 123  
      * @param file
 124  
      * @throws TagNotFoundException
 125  
      * @throws IOException
 126  
      * @param byteBuffer
 127  
      */
 128  
     public Lyrics3v2(ByteBuffer byteBuffer) throws TagNotFoundException, IOException
 129  0
     {
 130  
         try
 131  
         {
 132  0
             this.read(byteBuffer);
 133  
         }
 134  0
         catch (TagException e)
 135  
         {
 136  0
             e.printStackTrace();
 137  0
         }
 138  0
     }
 139  
 
 140  
     /**
 141  
      * @param field
 142  
      */
 143  
     public void setField(Lyrics3v2Field field)
 144  
     {
 145  0
         fieldMap.put(field.getIdentifier(), field);
 146  0
     }
 147  
 
 148  
     /**
 149  
      * Gets the value of the frame identified by identifier
 150  
      *
 151  
      * @param identifier The three letter code
 152  
      * @return The value associated with the identifier
 153  
      */
 154  
     public Lyrics3v2Field getField(String identifier)
 155  
     {
 156  0
         return fieldMap.get(identifier);
 157  
     }
 158  
 
 159  
     /**
 160  
      * @return
 161  
      */
 162  
     public int getFieldCount()
 163  
     {
 164  0
         return fieldMap.size();
 165  
     }
 166  
 
 167  
     /**
 168  
      * @return
 169  
      */
 170  
     public String getIdentifier()
 171  
     {
 172  0
         return "Lyrics3v2.00";
 173  
     }
 174  
 
 175  
     /**
 176  
      * @return
 177  
      */
 178  
     public int getSize()
 179  
     {
 180  0
         int size = 0;
 181  0
         Iterator<Lyrics3v2Field> iterator = fieldMap.values().iterator();
 182  
         Lyrics3v2Field field;
 183  
 
 184  0
         while (iterator.hasNext())
 185  
         {
 186  0
             field = iterator.next();
 187  0
             size += field.getSize();
 188  
         }
 189  
 
 190  
         // include LYRICSBEGIN, but not 6 char size or LYRICSEND
 191  0
         return 11 + size;
 192  
     }
 193  
 
 194  
 
 195  
     /**
 196  
      * @param obj
 197  
      * @return
 198  
      */
 199  
     public boolean equals(Object obj)
 200  
     {
 201  0
         if (!(obj instanceof Lyrics3v2))
 202  
         {
 203  0
             return false;
 204  
         }
 205  
 
 206  0
         Lyrics3v2 object = (Lyrics3v2) obj;
 207  
 
 208  0
         return this.fieldMap.equals(object.fieldMap) && super.equals(obj);
 209  
 
 210  
     }
 211  
 
 212  
     /**
 213  
      * @param identifier
 214  
      * @return
 215  
      */
 216  
     public boolean hasField(String identifier)
 217  
     {
 218  0
         return fieldMap.containsKey(identifier);
 219  
     }
 220  
 
 221  
     /**
 222  
      * @return
 223  
      */
 224  
     public Iterator<Lyrics3v2Field> iterator()
 225  
     {
 226  0
         return fieldMap.values().iterator();
 227  
     }
 228  
 
 229  
 
 230  
     /**
 231  
      * TODO implement
 232  
      *
 233  
      * @param byteBuffer
 234  
      * @return
 235  
      * @throws IOException
 236  
      */
 237  
     public boolean seek(ByteBuffer byteBuffer)
 238  
     {
 239  0
         return false;
 240  
     }
 241  
 
 242  
 
 243  
     public void read(ByteBuffer byteBuffer) throws TagException
 244  
     {
 245  
         long filePointer;
 246  
         int lyricSize;
 247  
 
 248  0
         if (seek(byteBuffer))
 249  
         {
 250  0
             lyricSize = seekSize(byteBuffer);
 251  
         }
 252  
         else
 253  
         {
 254  0
             throw new TagNotFoundException("Lyrics3v2.00 Tag Not Found");
 255  
         }
 256  
 
 257  
         // reset file pointer to the beginning of the tag;
 258  0
         seek(byteBuffer);
 259  0
         filePointer = byteBuffer.position();
 260  
 
 261  0
         fieldMap = new HashMap<String, Lyrics3v2Field>();
 262  
 
 263  
         Lyrics3v2Field lyric;
 264  
 
 265  
         // read each of the fields
 266  0
         while ((byteBuffer.position()) < (lyricSize - 11))
 267  
         {
 268  
             try
 269  
             {
 270  0
                 lyric = new Lyrics3v2Field(byteBuffer);
 271  0
                 setField(lyric);
 272  
             }
 273  0
             catch (InvalidTagException ex)
 274  
             {
 275  
                 // keep reading until we're done
 276  0
             }
 277  
         }
 278  0
     }
 279  
 
 280  
     /**
 281  
      * @param identifier
 282  
      */
 283  
     public void removeField(String identifier)
 284  
     {
 285  0
         fieldMap.remove(identifier);
 286  0
     }
 287  
 
 288  
     /**
 289  
      * @param file
 290  
      * @return
 291  
      * @throws IOException
 292  
      */
 293  
     public boolean seek(RandomAccessFile file) throws IOException
 294  
     {
 295  0
         byte[] buffer = new byte[11];
 296  
         String lyricEnd;
 297  
         String lyricStart;
 298  
         long filePointer;
 299  
         long lyricSize;
 300  
 
 301  
         // check right before the ID3 1.0 tag for the lyrics tag
 302  0
         file.seek(file.length() - 128 - 9);
 303  0
         file.read(buffer, 0, 9);
 304  0
         lyricEnd = new String(buffer, 0, 9);
 305  
 
 306  0
         if (lyricEnd.equals("LYRICS200"))
 307  
         {
 308  0
             filePointer = file.getFilePointer();
 309  
         }
 310  
         else
 311  
         {
 312  
             // check the end of the file for a lyrics tag incase an ID3
 313  
             // tag wasn't placed after it.
 314  0
             file.seek(file.length() - 9);
 315  0
             file.read(buffer, 0, 9);
 316  0
             lyricEnd = new String(buffer, 0, 9);
 317  
 
 318  0
             if (lyricEnd.equals("LYRICS200"))
 319  
             {
 320  0
                 filePointer = file.getFilePointer();
 321  
             }
 322  
             else
 323  
             {
 324  0
                 return false;
 325  
             }
 326  
         }
 327  
 
 328  
         // read the 6 bytes for the length of the tag
 329  0
         filePointer -= (9 + 6);
 330  0
         file.seek(filePointer);
 331  0
         file.read(buffer, 0, 6);
 332  
 
 333  0
         lyricSize = Integer.parseInt(new String(buffer, 0, 6));
 334  
 
 335  
         // read the lyrics begin tag if it exists.
 336  0
         file.seek(filePointer - lyricSize);
 337  0
         file.read(buffer, 0, 11);
 338  0
         lyricStart = new String(buffer, 0, 11);
 339  
 
 340  0
         return lyricStart.equals("LYRICSBEGIN");
 341  
     }
 342  
 
 343  
     /**
 344  
      * @return
 345  
      */
 346  
     public String toString()
 347  
     {
 348  0
         Iterator<Lyrics3v2Field> iterator = fieldMap.values().iterator();
 349  
         Lyrics3v2Field field;
 350  0
         String str = getIdentifier() + " " + this.getSize() + "\n";
 351  
 
 352  0
         while (iterator.hasNext())
 353  
         {
 354  0
             field = iterator.next();
 355  0
             str += (field.toString() + "\n");
 356  
         }
 357  
 
 358  0
         return str;
 359  
     }
 360  
 
 361  
     /**
 362  
      * @param identifier
 363  
      */
 364  
     public void updateField(String identifier)
 365  
     {
 366  
         Lyrics3v2Field lyrField;
 367  
 
 368  0
         if (identifier.equals("IND"))
 369  
         {
 370  0
             boolean lyricsPresent = fieldMap.containsKey("LYR");
 371  0
             boolean timeStampPresent = false;
 372  
 
 373  0
             if (lyricsPresent)
 374  
             {
 375  0
                 lyrField = fieldMap.get("LYR");
 376  
 
 377  0
                 FieldFrameBodyLYR lyrBody = (FieldFrameBodyLYR) lyrField.getBody();
 378  0
                 timeStampPresent = lyrBody.hasTimeStamp();
 379  
             }
 380  
 
 381  0
             lyrField = new Lyrics3v2Field(new FieldFrameBodyIND(lyricsPresent, timeStampPresent));
 382  0
             setField(lyrField);
 383  
         }
 384  0
     }
 385  
 
 386  
     /**
 387  
      * @param file
 388  
      * @throws IOException
 389  
      */
 390  
     public void write(RandomAccessFile file) throws IOException
 391  
     {
 392  0
         int offset = 0;
 393  
 
 394  
         long size;
 395  
         long filePointer;
 396  0
         byte[] buffer = new byte[6 + 9];
 397  
 
 398  
         String str;
 399  
         Lyrics3v2Field field;
 400  
         Iterator<Lyrics3v2Field> iterator;
 401  
         ID3v1Tag id3v1tag;
 402  0
         new ID3v1Tag();
 403  
 
 404  0
         id3v1tag = null;
 405  
 
 406  0
         delete(file);
 407  0
         file.seek(file.length());
 408  
 
 409  0
         filePointer = file.getFilePointer();
 410  
 
 411  0
         str = "LYRICSBEGIN";
 412  
 
 413  0
         for (int i = 0; i < str.length(); i++)
 414  
         {
 415  0
             buffer[i] = (byte) str.charAt(i);
 416  
         }
 417  
 
 418  0
         file.write(buffer, 0, str.length());
 419  
 
 420  
         // IND needs to go first. lets createField/update it and write it first.
 421  0
         updateField("IND");
 422  0
         field = fieldMap.get("IND");
 423  0
         field.write(file);
 424  
 
 425  0
         iterator = fieldMap.values().iterator();
 426  
 
 427  0
         while (iterator.hasNext())
 428  
         {
 429  0
             field = iterator.next();
 430  
 
 431  0
             String id = field.getIdentifier();
 432  0
             boolean save = TagOptionSingleton.getInstance().getLyrics3SaveField(id);
 433  
 
 434  0
             if ((!id.equals("IND")) && save)
 435  
             {
 436  0
                 field.write(file);
 437  
             }
 438  0
         }
 439  
 
 440  0
         size = file.getFilePointer() - filePointer;
 441  
 
 442  0
         if (this.getSize() != size)
 443  
         {
 444  
             //logger.info("Lyrics3v2 size didn't match up while writing.");
 445  
             //logger.info("this.getsize()     = " + this.getSize());
 446  
             //logger.info("size (filePointer) = " + size);
 447  
         }
 448  
 
 449  0
         str = Long.toString(size);
 450  
 
 451  0
         for (int i = 0; i < (6 - str.length()); i++)
 452  
         {
 453  0
             buffer[i] = (byte) '0';
 454  
         }
 455  
 
 456  0
         offset += (6 - str.length());
 457  
 
 458  0
         for (int i = 0; i < str.length(); i++)
 459  
         {
 460  0
             buffer[i + offset] = (byte) str.charAt(i);
 461  
         }
 462  
 
 463  0
         offset += str.length();
 464  
 
 465  0
         str = "LYRICS200";
 466  
 
 467  0
         for (int i = 0; i < str.length(); i++)
 468  
         {
 469  0
             buffer[i + offset] = (byte) str.charAt(i);
 470  
         }
 471  
 
 472  0
         offset += str.length();
 473  
 
 474  0
         file.write(buffer, 0, offset);
 475  
 
 476  0
         if (id3v1tag != null)
 477  
         {
 478  0
             id3v1tag.write(file);
 479  
         }
 480  0
     }
 481  
 
 482  
     /**
 483  
      * TODO
 484  
      * @param byteBuffer
 485  
      * @return
 486  
      */
 487  
     private int seekSize(ByteBuffer byteBuffer)
 488  
     {
 489  
         /*
 490  
         byte[] buffer = new byte[11];
 491  
         String lyricEnd = "";
 492  
         long filePointer = 0;
 493  
 
 494  
         // check right before the ID3 1.0 tag for the lyrics tag
 495  
         file.seek(file.length() - 128 - 9);
 496  
         file.read(buffer, 0, 9);
 497  
         lyricEnd = new String(buffer, 0, 9);
 498  
 
 499  
         if (lyricEnd.equals("LYRICS200"))
 500  
         {
 501  
             filePointer = file.getFilePointer();
 502  
         }
 503  
         else
 504  
         {
 505  
             // check the end of the file for a lyrics tag incase an ID3
 506  
             // tag wasn't placed after it.
 507  
             file.seek(file.length() - 9);
 508  
             file.read(buffer, 0, 9);
 509  
             lyricEnd = new String(buffer, 0, 9);
 510  
 
 511  
             if (lyricEnd.equals("LYRICS200"))
 512  
             {
 513  
                 filePointer = file.getFilePointer();
 514  
             }
 515  
             else
 516  
             {
 517  
                 return -1;
 518  
             }
 519  
         }
 520  
 
 521  
         // read the 6 bytes for the length of the tag
 522  
         filePointer -= (9 + 6);
 523  
         file.seek(filePointer);
 524  
         file.read(buffer, 0, 6);
 525  
 
 526  
         return Integer.parseInt(new String(buffer, 0, 6));
 527  
         */
 528  0
         return -1;
 529  
     }
 530  
 }