FileDocCategorySizeDatePackage
MyID3.javaAPI DocMyID3 for Android19451Wed Oct 08 18:12:02 BST 2008org.cmc.music.myid3

MyID3

public class MyID3 extends Object
The primary interface to the MyID3 library.

Almost all of the MyID3 library's core functionality can be accessed through it's methods.

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

Fields Summary
private boolean
skipId3v1
private boolean
skipId3v2
private boolean
skipId3v2Head
private boolean
skipId3v2Tail
private static final int
ID3v2_HEADER_LENGTH
Constructors Summary
Methods Summary
private longfindID3v2HeadLength(java.io.File file)

		if (file == null || !file.exists())
			return 0;

		long length = file.length();

		if (length < ID3v2_HEADER_LENGTH)
			return 0;

		InputStream is = null;
		try
		{
			is = new FileInputStream(file);
			is = new BufferedInputStream(is, 8192);

			byte header[];
			header = readArray(is, ID3v2_HEADER_LENGTH);

			if (header[0] != 0x49) // I
				return 0;
			if (header[1] != 0x44) // D
				return 0;
			if (header[2] != 0x33) // 3
				return 0;

			int flags = header[5];
			boolean has_footer = (flags & (1 << 4)) > 0;

			Number tagLength = MyID3v2Read.readSynchsafeInt(header, 6);
			if (tagLength == null)
				return 0;

			int totalLength = ID3v2_HEADER_LENGTH + tagLength.intValue();
			if (has_footer)
				totalLength += ID3v2_HEADER_LENGTH;

			return totalLength;
		} finally
		{
			try
			{
				if (is != null)
					is.close();
			} catch (IOException e)
			{

			}
		}
	
private intfindID3v2TailLength(java.io.File file, boolean hasId3v1)

		if (file == null || !file.exists())
			return 0;

		long length = file.length();

		int index = hasId3v1 ? 128 : 0;
		index += ID3v2_HEADER_LENGTH;

		if (index > length)
			return 0;

		InputStream is = null;
		try
		{
			is = new FileInputStream(file);
			is = new BufferedInputStream(is, 8192);

			is.skip(length - index);

			byte footer[];
			footer = readArray(is, ID3v2_HEADER_LENGTH);

			if (footer[0] != 0x33) // 3
				return 0;
			if (footer[1] != 0x44) // D
				return 0;
			if (footer[2] != 0x49) // I
				return 0;

			Number tagLength = MyID3v2Read.readSynchsafeInt(footer, 6);
			if (tagLength == null)
				return 0;

			int totalLength = ID3v2_HEADER_LENGTH + ID3v2_HEADER_LENGTH
					+ tagLength.intValue();

			return totalLength;
		} finally
		{
			try
			{
				if (is != null)
					is.close();
			} catch (IOException e)
			{

			}
		}
	
private booleanhasID3v1(java.io.File file)

		if (file == null || !file.exists())
			return false;

		long length = file.length();

		if (length < 128)
			return false;

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

			is.skip(length - 128);

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

			}
		}

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

		return true;
	
public org.cmc.music.metadata.MusicMetadataSetread(java.io.File file)
Reads all metadata (ID3v1 & ID3v2) from MP3 file.

param
file File to read metadata (ie. song data) from.
return
MusicMetadataSet, a set of MusicMetadata value collections.
see
MusicMetadataSet, MusicMetadata

		return read(file, null);
	
public org.cmc.music.metadata.MusicMetadataSetread(java.io.File file, org.cmc.music.myid3.MyID3Listener listener)
Reads all metadata (ID3v1 & ID3v2) from MP3 file.

param
file File to read metadata (ie. song data) from.
param
listener MyID3Listener, an observer.
return
MusicMetadataSet, a set of MusicMetadata value collections.
see
MusicMetadataSet, MusicMetadata

		try
		{
			if (file == null || !file.exists())
				return null;

			if (!file.getName().toLowerCase().endsWith(".mp3"))
				return null;
			
			ID3Tag id3v1 = readID3v1(listener, file);
			ID3Tag.V2 id3v2 = readID3v2(listener, file, id3v1 != null);

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

			return result;
		} catch (Error e)
		{

			throw e;
		} catch (IOException e)
		{

			throw e;
		}
	
private final byte[]readArray(java.io.InputStream is, int length)

		byte result[] = new byte[length];
		int total = 0;
		while (total < length)
		{
			int read = is.read(result, total, length - total);
			if (read < 0)
				throw new IOException("bad read");
			total += read;
		}
		return result;
	
private org.cmc.music.myid3.ID3TagreadID3v1(java.io.File file)

		return readID3v1(null, file);
	
private org.cmc.music.myid3.ID3TagreadID3v1(org.cmc.music.myid3.MyID3Listener listener, java.io.File file)

		if (file == null || !file.exists())
			return null;

		long length = file.length();

		if (length < 128)
			return null;

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

			is.skip(length - 128);

			bytes = readArray(is, 128);
		} finally
		{
			try
			{
				if (is != null)
					is.close();
			} catch (IOException 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.");

		MyID3v1 id3v1 = new MyID3v1();
		MusicMetadata tags = id3v1.parseTags(listener, bytes);

		return new ID3Tag.V1(bytes, tags);
	
private org.cmc.music.myid3.ID3Tag$V2readID3v2(org.cmc.music.myid3.MyID3Listener listener, java.io.File file, boolean hasId3v1)

		if (file == null || !file.exists())
			return null;

		byte bytes[] = null;
		bytes = readID3v2Tail(file, hasId3v1);
		if (bytes == null)
			bytes = readID3v2Head(file);

		if (bytes == null)
			return null;

		if (null != listener)
			listener.log("ID3v2 tag found: " + bytes.length + " bytes");

		MyID3v2Read parser = new MyID3v2Read(listener,
				new ByteArrayInputStream(bytes), false);
		while (!parser.isComplete())
		{
			parser.iteration();
		}
		if (parser.isError())
		{
			if (listener != null)
				listener.log("id3v2 error", parser.getErrorMessage());
			
			parser.dump();
			return null;
		}

		if (!parser.hasTags())
			return null;

		Vector tags = parser.getTags();

		MusicMetadata values = new ID3v2DataMapping().process(tags);

		byte version_major = parser.getVersionMajor();
		byte version_minor = parser.getVersionMinor();

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

		return new ID3Tag.V2(version_major, version_minor, bytes, values, tags);
	
private byte[]readID3v2Head(java.io.File file)


	     
	

		if (file == null || !file.exists())
			return null;

		long length = file.length();

		if (length < ID3v2_HEADER_LENGTH)
			return null;

		InputStream is = null;
		try
		{
			is = new FileInputStream(file);
			is = new BufferedInputStream(is, 8192);

			byte header[];
			header = readArray(is, ID3v2_HEADER_LENGTH);

			if (header[0] != 0x49) // I
				return null;
			if (header[1] != 0x44) // D
				return null;
			if (header[2] != 0x33) // 3
				return null;

			int flags = header[5];
			boolean has_footer = (flags & (1 << 4)) > 0;

			Number tagLength = MyID3v2Read.readSynchsafeInt(header, 6);
			if (tagLength == null)
				return null;

			int bodyLength = tagLength.intValue();
			if (has_footer)
				bodyLength += ID3v2_HEADER_LENGTH;

			if (ID3v2_HEADER_LENGTH + bodyLength > length)
				return null;

			byte body[] = readArray(is, bodyLength);

			byte result[] = new byte[header.length + body.length];

			System.arraycopy(header, 0, result, 0, header.length);
			System.arraycopy(body, 0, result, header.length, body.length);

			return result;
		} finally
		{
			try
			{
				if (is != null)
					is.close();
			} catch (IOException e)
			{

			}
		}
	
private byte[]readID3v2Tail(java.io.File file, boolean hasId3v1)

		if (file == null || !file.exists())
			return null;

		long length = file.length();

		int index = hasId3v1 ? 128 : 0;
		index += ID3v2_HEADER_LENGTH;

		if (index > length)
			return null;

		InputStream is = null;
		try
		{
			is = new FileInputStream(file);
			is = new BufferedInputStream(is, 8192);

			is.skip(length - index);

			byte footer[];
			footer = readArray(is, ID3v2_HEADER_LENGTH);

			if (footer[2] != 0x33) // 3
				return null;
			if (footer[1] != 0x44) // D
				return null;
			if (footer[0] != 0x49) // I
				return null;

			Number tagLength = MyID3v2Read.readSynchsafeInt(footer, 6);
			if (tagLength == null)
				return null;

			int bodyLength = tagLength.intValue();
			if (index + bodyLength > length)
				return null;

			is.close();
			is = null;

			is = new FileInputStream(file);
			is = new BufferedInputStream(is, 8192);

			long skip = length;
			skip -= ID3v2_HEADER_LENGTH;
			skip -= bodyLength;
			skip -= ID3v2_HEADER_LENGTH;
			if (hasId3v1)
				skip -= 128;
			is.skip(skip);

			byte header_and_body[] = readArray(is, ID3v2_HEADER_LENGTH
					+ bodyLength + ID3v2_HEADER_LENGTH);

			byte result[] = header_and_body;

			return result;
		} finally
		{
			try
			{
				if (is != null)
					is.close();
			} catch (IOException e)
			{

			}
		}
	
public voidremoveTags(java.io.File src, java.io.File dst)
Removes all ID3v1 and ID3v2 tags from an mp3 file.

param
src File to read non-metadata (ie. song data) from.
param
dst File to overwrite with new mp3 file.

		byte id3v1Tag[] = null;
		byte id3v2HeadTag[] = null;
		byte id3v2TailTag[] = null;

		write(src, dst, id3v1Tag, id3v2HeadTag, id3v2TailTag);
	
public voidrewriteTags(java.io.File src, java.io.File dst)
Removes all ID3v1 and ID3v2 tags from an mp3 file.

param
src File to read non-metadata (ie. song data) from.
param
dst File to overwrite with new mp3 file.

		byte id3v1Tag[] = null;
		ID3Tag tag = readID3v1(src);
		if (null != tag)
			id3v1Tag = tag.bytes;

		byte id3v2HeadTag[] = readID3v2Head(src);

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

		write(src, dst, id3v1Tag, id3v2HeadTag, id3v2TailTag);
	
public voidsetSkipId3v1()
Configures the library to not write ID3v1 tags.


	        	 
	  
	
		skipId3v1 = true;
	
public voidsetSkipId3v2()
Configures the library to not write ID3v2 tags.


	        	 
	  
	
		skipId3v2 = true;
	
public voidsetSkipId3v2Head()
Configures the library to not write ID3v2 head tags.


	         	 
	  
	
		skipId3v2Head = true;
	
public voidsetSkipId3v2Tail()
Configures the library to not write ID3v2 tail tags.


	         	 
	  
	
		skipId3v2Tail = true;
	
public voidupdate(java.io.File file, org.cmc.music.metadata.MusicMetadataSet set, org.cmc.music.metadata.MusicMetadata values)
Write MP3 file with specific metadata, drawing song data from an existing mp3 file.

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 MusicMetadata, a specific group of values to write.
see
MusicMetadataSet, MusicMetadata

		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
		{

		}
	
public voidupdate(java.io.File file, org.cmc.music.metadata.MusicMetadataSet set, org.cmc.music.metadata.MusicMetadata values, MyID3v2Write.Filter filter, org.cmc.music.myid3.MyID3Listener listener)
Write MP3 file with specific metadata, drawing song data from an existing mp3 file.

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 MusicMetadata, 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, MusicMetadata, MyID3Listener, MyID3v2Write.Filter


		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;
		}
	
private voidwrite(java.io.File src, java.io.File dst, byte[] id3v1Tag, byte[] id3v2HeadTag, byte[] id3v2TailTag)

		if (src == null || !src.exists())


		if (!src.getName().toLowerCase().endsWith(".mp3"))


		if (dst == null)


		if (dst.exists())
		{
			dst.delete();

		}

		boolean hasId3v1 = hasID3v1(src);

		long id3v1Length = hasId3v1 ? 128 : 0;
		long id3v2HeadLength = findID3v2HeadLength(src);
		long id3v2TailLength = 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, 8192);

			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)
			{

			}
			try
			{
				if (os != null)
					os.close();
			} catch (Throwable e)
			{

			}
		}
	
public voidwrite(java.io.File src, java.io.File dst, org.cmc.music.metadata.MusicMetadataSet set, org.cmc.music.metadata.MusicMetadata values)
Write MP3 file with specific metadata, drawing song data from an existing mp3 file.

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 MusicMetadata, a specific group of values to write.
see
MusicMetadataSet, MusicMetadata

		write(src, dst, set, values, null, null);
	
public voidwrite(java.io.File src, java.io.File dst, org.cmc.music.metadata.MusicMetadataSet set, org.cmc.music.metadata.MusicMetadata values, org.cmc.music.myid3.MyID3Listener listener)
Write MP3 file with specific metadata, drawing song data from an existing mp3 file.

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 MusicMetadata, a specific group of values to write.
param
listener MyID3Listener, observer of the write process.
see
MusicMetadataSet, MusicMetadata, MyID3Listener

		write(src, dst, set, values, null, listener);
	
public voidwrite(java.io.File src, java.io.File dst, org.cmc.music.metadata.MusicMetadataSet set, org.cmc.music.metadata.MusicMetadata values, MyID3v2Write.Filter filter, org.cmc.music.myid3.MyID3Listener listener)
Write MP3 file with specific metadata, drawing song data from an existing mp3 file.

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 MusicMetadata, 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, MusicMetadata, MyID3Listener, MyID3v2Write.Filter

		if (values == null)


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

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

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

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

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