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