Package org.cmc.music.myid3.id3v1

Source Code of org.cmc.music.myid3.id3v1.MyID3v1

/*
* Written By Charles M. Chen
*
* Created on Jan 1, 2006
*
*/

package org.cmc.music.myid3.id3v1;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.cmc.music.common.ID3v1Genre;
import org.cmc.music.metadata.IMusicMetadata;
import org.cmc.music.metadata.MusicMetadata;
import org.cmc.music.metadata.MusicMetadataConstants;
import org.cmc.music.myid3.ID3Tag;
import org.cmc.music.myid3.MyID3Listener;
import org.cmc.music.util.Debug;
import org.cmc.music.util.FileUtils;

public class MyID3v1 implements MusicMetadataConstants, MyID3v1Constants
{

  public byte[] toTag(MyID3Listener listener, IMusicMetadata values,
      boolean strict) throws UnsupportedEncodingException
  {
    byte result[] = new byte[ID3_V1_TAG_LENGTH];

    int index = 0;
    result[index++] = 0x54; // T
    result[index++] = 0x41; // A
    result[index++] = 0x47; // G

    writeField(result, index, 30, values.getSongTitle());
    index += 30;

    writeField(result, index, 30, values.getArtist());
    index += 30;

    writeField(result, index, 30, values.getAlbum());
    index += 30;

    {
      Number value = values.getYear();
      writeField(result, index, 4, value == null ? null : "" + value);
      index += 4;
    }

    Number trackNumber = null;
    {
      Number value = values.getTrackNumberNumeric();

      if (value != null && value.intValue() >= 0
          && value.intValue() < 256)
        trackNumber = value;
    }

    String comment = null;
    if (values.getComments().size() > 0)
      comment = (String) values.getComments().get(0);

    // TODO: should we ignore 0x00 and 0xff track numbers?
    if (trackNumber == null)
    {
      writeField(result, index, 30, comment);
      index += 30;
    } else
    {
      writeField(result, index, 28, comment);
      index += 28;

      result[index++] = 0;
      result[index++] = (byte) trackNumber.intValue();
    }

    {
      Object o = values.getGenreID();
      if (o == null)
        o = values.getGenreName();

      if (o != null && (o instanceof String))
      {
        String genre_name = (String) o;
        Number genre_id = ID3v1Genre.getIDForName(genre_name);
        if (genre_id != null)
        {
          o = genre_id;
          // Debug.debug("fixed genre", genre_name);
          // Debug.debug("fixed genre", genre_id);
          // Debug.dumpStack();
        }
      }

      if (o != null && !(o instanceof Number))
      {
        if (null != listener)
          listener.log("Discarding invalid genre in ID3v1 tag", o
              + " (" + Debug.getType(o) + ")");
        // Debug.dumpStack();
      } else
      {
        Number value = (Number) o;

        if (value != null && value.intValue() >= 0
            && value.intValue() < 80)
          result[index++] = (byte) value.intValue();
        else
          result[index++] = 0;
      }
    }

    // Debug.debug("index", index);

    return result;
  }

  private void writeField(byte bytes[], int start, int max_length, String s)
      throws UnsupportedEncodingException
  {
    if (s == null)
    {
      for (int i = 0; i < max_length; i++)
        bytes[i + start] = 0;
      return;
    }

    byte value[] = s.getBytes(DEFAULT_CHAR_ENCODING);
    int count = Math.min(value.length, max_length);
    for (int i = 0; i < count; i++)
      bytes[i + start] = value[i];
    for (int i = count; i < max_length; i++)
      bytes[i + start] = 0;
  }

  // private boolean isValidIso8859(byte bytes[], int start, int length)
  // {
  // for (int i = start; i < start + length; i++)
  // {
  // int value = 0xff & bytes[i];
  // if (value >= 0x20 && value <= 0x7E)
  // ;
  // else if (value >= 0xA0 && value <= 0xFF)
  // ;
  // else
  // {
  // Debug.debug("bad byte[" + i + "/" + length + "]: " + value
  // + " (0x" + Integer.toHexString(value) + "");
  // return false;
  // }
  // }
  // return true;
  // }

  private String getField(MyID3Listener listener, byte bytes[], int start,
      int length)
  {
    for (int i = start; i < start + length; i++)
    {
      if (bytes[i] == 0)
      {
        length = i - start;
        break;
      }
    }
    // if (null != listener)
    // listener
    // .log("isValidIso8859", isValidIso8859(bytes, start, length));

    if (length > 0)
    {
      try
      {
        String result = new String(bytes, start, length,
            DEFAULT_CHAR_ENCODING);
        result = result.trim();
        if (result.length() < 1)
          return null;
        return result;
      } catch (Throwable e)
      {
        Debug.debug(e);
      }
    }

    return null;
  }

  public IMusicMetadata parseTags(byte bytes[], boolean strict)
  {
    return parseTags(null, bytes, strict);
  }

  public IMusicMetadata parseTags(MyID3Listener listener, byte bytes[],
      boolean strict)
  {
    IMusicMetadata result = new MusicMetadata("ID3v1");

    int counter = 3;
    String title = getField(listener, bytes, counter, 30);
    counter += 30;
    result.setSongTitle(title);
    if (null != listener)
      listener.logWithLength("id3v1 title", title);

    String artist = getField(listener, bytes, counter, 30);
    counter += 30;
    result.setArtist(artist);
    if (null != listener)
      listener.logWithLength("id3v1 artist", artist);

    String album = getField(listener, bytes, counter, 30);
    counter += 30;
    result.setAlbum(album);
    if (null != listener)
      listener.logWithLength("id3v1 album", album);

    String yearString = getField(listener, bytes, counter, 4);
    counter += 4;
    Number year = null;
    try
    {
      if (null != yearString)
        year = Integer.valueOf(yearString);
    } catch (NumberFormatException e)
    {
      // ignore
    }
    result.setYear(year);
    if (null != listener)
    {
      listener.logWithLength("id3v1 year", yearString);
      if (null != yearString)
        listener.log("id3v1 year", year);
    }

    String comment = getField(listener, bytes, counter, 30);
    counter += 30;
    if (null != comment)
      result.addComment(comment);
    if (null != listener)
      listener.logWithLength("id3v1 comment", comment);

    if (bytes[counter - 2] == 0 && bytes[counter - 1] != 0)
    {
      int trackNumber = 0xff & bytes[counter - 1];
      // TODO: should we ignore 0x00 and 0xff track numbers?
      result.setTrackNumberNumeric(new Integer(trackNumber));

      if (null != listener)
        listener.log("id3v1 trackNumber: " + trackNumber);
    }

    int genre = 0xff & bytes[counter];
    if (genre < 80 && genre > 0)
    {
      result.setGenreID(new Integer(genre));
      result.setGenreName(ID3v1Genre.getNameForID(new Integer(genre)));

      if (null != listener)
        listener.log("id3v1 genre: " + genre);
    }

    if (null != listener)
      listener.log();

    return result;
  }

  public boolean hasID3v1(File file) throws IOException
  {
    if (file == null || !file.exists())
      return false;

    long length = file.length();

    if (length < ID3_V1_TAG_LENGTH)
      return false;

    byte bytes[];
    InputStream is = null;
    try
    {
      is = new FileInputStream(file);
      is = new BufferedInputStream(is);

      is.skip(length - ID3_V1_TAG_LENGTH);

      bytes = FileUtils.readArray(is, ID3_V1_TAG_LENGTH);
    } finally
    {
      try
      {
        if (is != null)
          is.close();
      } catch (IOException e)
      {
        Debug.debug(e);
      }
    }

    if (bytes[0] != 'T')
      return false;
    if (bytes[1] != 'A')
      return false;
    if (bytes[2] != 'G')
      return false;

    return true;
  }

  public ID3Tag readID3v1(File file, boolean strict) throws IOException
  {
    return readID3v1(null, file, strict);
  }

  public ID3Tag.V1 readID3v1(MyID3Listener listener, File file, boolean strict)
      throws IOException
  {
    if (file == null || !file.exists())
      return null;

    long length = file.length();

    if (length < ID3_V1_TAG_LENGTH)
      return null;

    byte bytes[];
    InputStream is = null;
    try
    {
      is = new FileInputStream(file);
      is = new BufferedInputStream(is);

      is.skip(length - ID3_V1_TAG_LENGTH);

      bytes = FileUtils.readArray(is, ID3_V1_TAG_LENGTH);
    } finally
    {
      try
      {
        if (is != null)
          is.close();
      } catch (IOException e)
      {
        Debug.debug(e);
      }
    }

    if (bytes[0] != 'T')
      return null;
    if (bytes[1] != 'A')
      return null;
    if (bytes[2] != 'G')
      return null;

    if (null != listener)
      listener.log("ID3v1 tag found.");

    IMusicMetadata tags = new MyID3v1().parseTags(listener, bytes, strict);

    return new ID3Tag.V1(bytes, tags);
  }

}
TOP

Related Classes of org.cmc.music.myid3.id3v1.MyID3v1

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.