Package org.cmc.music.myid3

Source Code of org.cmc.music.myid3.MyID3

package org.cmc.music.myid3;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.cmc.music.common.ID3ReadException;
import org.cmc.music.common.ID3WriteException;
import org.cmc.music.metadata.IMusicMetadata;
import org.cmc.music.metadata.MusicMetadataSet;
import org.cmc.music.myid3.id3v1.MyID3v1;
import org.cmc.music.myid3.id3v1.MyID3v1Constants;
import org.cmc.music.myid3.id3v2.MyID3v2;
import org.cmc.music.myid3.id3v2.MyID3v2Write;
import org.cmc.music.util.Debug;

/**
* The primary interface to the MyID3 library.
* <p>
* Almost all of the MyID3 library's core functionality can be accessed through
* it's methods.
* <p>
* See the source of the SampleUsage class and other classes in the
* org.cmc.music.myid3.examples package for examples.
*
* @see org.cmc.music.myid3.examples.SampleUsage
*/
public class MyID3 implements MyID3v1Constants
{
  /**
   * Write MP3 file with specific metadata, drawing song data from an existing
   * mp3 file.
   * <p>
   *
   * @param file
   *            File to read non-metadata (ie. song data) from. Will be
   *            overwritten with new mp3 file.
   * @param set
   *            MusicMetadataSet, usually read from mp3 file.
   * @param values
   *            IMusicMetadata, a specific group of values to write.
   * @see MusicMetadataSet, IMusicMetadata
   */
  public void update(File file, MusicMetadataSet set, IMusicMetadata values)
      throws UnsupportedEncodingException, IOException, ID3WriteException
  {
    File temp = null;
    try
    {
      temp = File.createTempFile(file.getName(), ".tmp", file
          .getParentFile());
      write(file, temp, set, values);
      temp.setLastModified(file.lastModified());
      file.delete();
      temp.renameTo(file);
    } finally
    {

    }
  }

  /**
   * Write MP3 file with specific metadata, drawing song data from an existing
   * mp3 file.
   * <p>
   *
   * @param file
   *            File to read non-metadata (ie. song data) from. Will be
   *            overwritten with new mp3 file.
   * @param set
   *            MusicMetadataSet, usually read from mp3 file.
   * @param values
   *            IMusicMetadata, a specific group of values to write.
   * @param filter
   *            MyID3v2Write.Filter, can be used to prevent ID3v2 frames from
   *            written on a case-by-case basis.
   * @param listener
   *            MyID3Listener, observer of the write process.
   * @see MusicMetadataSet, IMusicMetadata, MyID3Listener, MyID3v2Write.Filter
   */
  public void update(File file, MusicMetadataSet set, IMusicMetadata values,
      MyID3v2Write.Filter filter, MyID3Listener listener)
      throws UnsupportedEncodingException, IOException, ID3WriteException
  {

    File temp = null;
    try
    {
      temp = File.createTempFile(file.getName(), ".tmp", file
          .getParentFile());

      write(file, temp, set, values, filter, listener);
      temp.setLastModified(file.lastModified());
      file.delete();
      temp.renameTo(file);
    } catch (UnsupportedEncodingException e)
    {
      if (temp != null && temp.exists() && file.exists())
        temp.delete();
      throw e;
    } catch (IOException e)
    {
      if (temp != null && temp.exists() && file.exists())
        temp.delete();
      throw e;
    } catch (ID3WriteException e)
    {
      if (temp != null && temp.exists() && file.exists())
        temp.delete();
      throw e;
    }
  }

  /**
   * Write MP3 file with specific metadata, drawing song data from an existing
   * mp3 file.
   * <p>
   *
   * @param src
   *            File to read non-metadata (ie. song data) from.
   * @param dst
   *            File to overwrite with new mp3 file.
   * @param set
   *            MusicMetadataSet, usually read from mp3 file.
   * @param values
   *            IMusicMetadata, a specific group of values to write.
   * @see MusicMetadataSet, IMusicMetadata
   */
  public void write(File src, File dst, MusicMetadataSet set,
      IMusicMetadata values) throws UnsupportedEncodingException,
      IOException, ID3WriteException
  {
    write(src, dst, set, values, null, null);
  }

  /**
   * Write MP3 file with specific metadata, drawing song data from an existing
   * mp3 file.
   * <p>
   *
   * @param src
   *            File to read non-metadata (ie. song data) from.
   * @param dst
   *            File to overwrite with new mp3 file.
   * @param set
   *            MusicMetadataSet, usually read from mp3 file.
   * @param values
   *            IMusicMetadata, a specific group of values to write.
   * @param listener
   *            MyID3Listener, observer of the write process.
   * @see MusicMetadataSet, IMusicMetadata, MyID3Listener
   */
  public void write(File src, File dst, MusicMetadataSet set,
      IMusicMetadata values, MyID3Listener listener)
      throws UnsupportedEncodingException, IOException, ID3WriteException
  {
    write(src, dst, set, values, null, listener);
  }

  /**
   * Write MP3 file with specific metadata, drawing song data from an existing
   * mp3 file.
   * <p>
   *
   * @param src
   *            File to read non-metadata (ie. song data) from.
   * @param dst
   *            File to overwrite with new mp3 file.
   * @param set
   *            MusicMetadataSet, usually read from mp3 file.
   * @param values
   *            IMusicMetadata, a specific group of values to write.
   * @param filter
   *            MyID3v2Write.Filter, can be used to prevent ID3v2 frames from
   *            written on a case-by-case basis.
   * @param listener
   *            MyID3Listener, observer of the write process.
   * @see MusicMetadataSet, IMusicMetadata, MyID3Listener, MyID3v2Write.Filter
   */
  public void write(File src, File dst, MusicMetadataSet set,
      IMusicMetadata values, MyID3v2Write.Filter filter,
      MyID3Listener listener) throws UnsupportedEncodingException,
      IOException, ID3WriteException
  {
    if (values == null)
      throw new IOException(Debug.getDebug("missing values", values));

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

    byte id3v1Tag[] = new MyID3v1().toTag(listener, values, strict);
    if (listener != null)
      listener.log("writing id3v1Tag", id3v1Tag == null ? "null" : ""
          + id3v1Tag.length);

    byte id3v2TailTag[] = new MyID3v2Write().toTag(listener, filter, set,
        values, strict);
    if (listener != null)
      listener.log("writing id3v2TailTag", id3v2TailTag == null ? "null"
          : "" + id3v2TailTag.length);

    write(src, dst, id3v1Tag, id3v2TailTag, id3v2TailTag);

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

  /**
   * Removes all ID3v1 and ID3v2 tags from an mp3 file.
   * <p>
   *
   * @param src
   *            File to read non-metadata (ie. song data) from.
   * @param dst
   *            File to overwrite with new mp3 file.
   */
  public void removeTags(File src, File dst)
      throws UnsupportedEncodingException, IOException, ID3WriteException
  {
    byte id3v1Tag[] = null;
    byte id3v2HeadTag[] = null;
    byte id3v2TailTag[] = null;

    write(src, dst, id3v1Tag, id3v2HeadTag, id3v2TailTag);
  }

  /**
   * Removes all ID3v1 and ID3v2 tags from an mp3 file.
   * <p>
   *
   * @param src
   *            File to read non-metadata (ie. song data) from.
   * @param dst
   *            File to overwrite with new mp3 file.
   */
  public void rewriteTags(File src, File dst)
      throws UnsupportedEncodingException, IOException, ID3WriteException
  {
    byte id3v1Tag[] = null;
    ID3Tag tag = new MyID3v1().readID3v1(src, strict);
    if (null != tag)
      id3v1Tag = tag.bytes;

    byte id3v2HeadTag[] = new MyID3v2().readID3v2Head(src, strict);

    boolean hasId3v1 = id3v1Tag != null;
    byte id3v2TailTag[] = new MyID3v2()
        .readID3v2Tail(src, hasId3v1, strict);

    write(src, dst, id3v1Tag, id3v2HeadTag, id3v2TailTag);
  }

  private boolean strict = false;

  /**
   * Configures the library to not write ID3v1 tags.
   */
  public void setStrict()
  {
    strict = true;
  }

  private boolean skipId3v1 = false;

  /**
   * Configures the library to not write ID3v1 tags.
   */
  public void setSkipId3v1()
  {
    skipId3v1 = true;
  }

  private boolean skipId3v2 = false;

  /**
   * Configures the library to not write ID3v2 tags.
   */
  public void setSkipId3v2()
  {
    skipId3v2 = true;
  }

  private boolean skipId3v2Head = false;

  /**
   * Configures the library to not write ID3v2 head tags.
   */
  public void setSkipId3v2Head()
  {
    skipId3v2Head = true;
  }

  private boolean skipId3v2Tail = false;

  /**
   * Configures the library to not write ID3v2 tail tags.
   */
  public void setSkipId3v2Tail()
  {
    skipId3v2Tail = true;
  }

  private void write(File src, File dst, byte id3v1Tag[],
      byte id3v2HeadTag[], byte id3v2TailTag[]) throws IOException
  {
    if (src == null || !src.exists())
      throw new IOException(Debug.getDebug("missing src", src));

    if (!src.getName().toLowerCase().endsWith(".mp3"))
      throw new IOException(Debug.getDebug("src not mp3", src));

    if (dst == null)
      throw new IOException(Debug.getDebug("missing dst", dst));

    if (dst.exists())
    {
      dst.delete();
      if (dst.exists())
        throw new IOException(Debug.getDebug("could not delete dst",
            dst));
    }

    boolean hasId3v1 = new MyID3v1().hasID3v1(src);

    long id3v1Length = hasId3v1 ? ID3_V1_TAG_LENGTH : 0;
    long id3v2HeadLength = new MyID3v2().findID3v2HeadLength(src);
    long id3v2TailLength = new MyID3v2().findID3v2TailLength(src, hasId3v1);

    OutputStream os = null;
    InputStream is = null;
    try
    {
      dst.getParentFile().mkdirs();
      os = new FileOutputStream(dst);
      os = new BufferedOutputStream(os);

      if (!skipId3v2Head && !skipId3v2 && id3v2HeadTag != null)
        os.write(id3v2HeadTag);

      is = new FileInputStream(src);
      is = new BufferedInputStream(is);

      is.skip(id3v2HeadLength);

      long total_to_read = src.length();
      total_to_read -= id3v1Length;
      total_to_read -= id3v2HeadLength;
      total_to_read -= id3v2TailLength;

      byte buffer[] = new byte[1024];
      long total_read = 0;
      while (total_read < total_to_read)
      {
        int remainder = (int) (total_to_read - total_read);
        int readSize = Math.min(buffer.length, remainder);
        int read = is.read(buffer, 0, readSize);
        if (read <= 0)
          throw new IOException("unexpected EOF");

        os.write(buffer, 0, read);
        total_read += read;
      }

      if (!skipId3v2Tail && !skipId3v2 && id3v2TailTag != null)
        os.write(id3v2TailTag);
      if (!skipId3v1 && id3v1Tag != null)
        os.write(id3v1Tag);
    } finally
    {
      try
      {
        if (is != null)
          is.close();
      } catch (Throwable e)
      {
        Debug.debug(e);
      }
      try
      {
        if (os != null)
          os.close();
      } catch (Throwable e)
      {
        Debug.debug(e);
      }
    }
  }

  /**
   * Reads all metadata (ID3v1 & ID3v2) from MP3 file.
   * <p>
   *
   * @param file
   *            File to read metadata (ie. song data) from.
   * @return MusicMetadataSet, a set of IMusicMetadata value collections.
   * @see MusicMetadataSet, IMusicMetadata
   */
  public MusicMetadataSet read(File file) throws IOException,
      ID3ReadException
  {
    return read(file, null);
  }

  /**
   * Reads all metadata (ID3v1 & ID3v2) from MP3 file.
   * <p>
   *
   * @param file
   *            File to read metadata (ie. song data) from.
   * @param listener
   *            MyID3Listener, an observer.
   * @return MusicMetadataSet, a set of IMusicMetadata value collections.
   * @see MusicMetadataSet, IMusicMetadata
   */
  public MusicMetadataSet read(File file, MyID3Listener listener)
      throws IOException, ID3ReadException
  {
    try
    {
      if (file == null || !file.exists())
        return null;

      if (!file.getName().toLowerCase().endsWith(".mp3"))
        return null;

      ID3Tag.V1 id3v1 = new MyID3v1().readID3v1(listener, file, strict);
      ID3Tag.V2 id3v2 = new MyID3v2().readID3v2(listener, file,
          id3v1 != null, strict);

      MusicMetadataSet result = MusicMetadataSet.factoryMethod(id3v1,
          id3v2, file.getName(), file.getParentFile().getName());

      return result;
    } catch (Error e)
    {
      Debug.debug("file", file);
      throw e;
    } catch (IOException e)
    {
      Debug.debug("file", file);
      throw e;
    }
  }

}
TOP

Related Classes of org.cmc.music.myid3.MyID3

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.