/*
* Entagged Audio Tag library
* Copyright (c) 2004-2005 Christian Laireiter <liree@web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jaudiotagger.audio.asf.io;
import org.jaudiotagger.audio.asf.data.AsfHeader;
import org.jaudiotagger.audio.asf.data.GUID;
import org.jaudiotagger.audio.asf.util.Utils;
import java.io.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* This <i>class </i> reads an ASF header out of an input stream an creates an
* {@link org.jaudiotagger.audio.asf.data.AsfHeader} object if successful. <br>
* For now only ASF ver 1.0 is supported, because ver 2.0 seems not to be used
* anywhere. <br>
* ASF headers contains other chunks. As of this other readers of current
* <b>package </b> are called from within.
*
* @author Christian Laireiter
*/
public class AsfHeaderReader extends ChunkContainerReader<AsfHeader> {
/**
* The GUID this reader {@linkplain #getApplyingIds() applies to}
*/
private final static GUID[] APPLYING = { GUID.GUID_HEADER };
/**
* ASF reader configured to extract all information.
*/
private final static AsfHeaderReader FULL_READER;
/**
* ASF reader configured to just extract information about audio streams.<br>
* If the ASF file only contains one audio stream it works fine.<br>
*/
private final static AsfHeaderReader INFO_READER;
/**
* ASF reader configured to just extract metadata information.<br>
*/
private final static AsfHeaderReader TAG_READER;
static {
final List<Class<? extends ChunkReader>> readers = new ArrayList<Class<? extends ChunkReader>>();
readers.add(FileHeaderReader.class);
readers.add(StreamChunkReader.class);
INFO_READER = new AsfHeaderReader(readers, true);
readers.clear();
readers.add(ContentDescriptionReader.class);
readers.add(ContentBrandingReader.class);
readers.add(LanguageListReader.class);
readers.add(MetadataReader.class);
/*
* Create the header extension object readers with just content
* description reader, extended content description reader, language
* list reader and both metadata object readers.
*/
final AsfExtHeaderReader extReader = new AsfExtHeaderReader(readers,
true);
final AsfExtHeaderReader extReader2 = new AsfExtHeaderReader(readers,
true);
TAG_READER = new AsfHeaderReader(readers, true);
TAG_READER.setExtendedHeaderReader(extReader);
readers.add(FileHeaderReader.class);
readers.add(StreamChunkReader.class);
readers.add(EncodingChunkReader.class);
readers.add(EncryptionChunkReader.class);
readers.add(StreamBitratePropertiesReader.class);
FULL_READER = new AsfHeaderReader(readers, false);
FULL_READER.setExtendedHeaderReader(extReader2);
}
/**
* Creates a Stream that will read from the specified
* {@link RandomAccessFile};<br>
*
* @param raf
* data source to read from.
* @return a stream which accesses the source.
*/
private static InputStream createStream(final RandomAccessFile raf) {
return new FullRequestInputStream(new BufferedInputStream(
new RandomAccessFileInputstream(raf)));
}
/**
* This method extracts the full ASF-Header from the given file.<br>
* If no header could be extracted <code>null</code> is returned. <br>
*
* @param file
* the ASF file to read.<br>
* @return AsfHeader-Wrapper, or <code>null</code> if no supported ASF
* header was found.
* @throws IOException
* on I/O Errors.
*/
public static AsfHeader readHeader(final File file) throws IOException {
final InputStream stream = new FileInputStream(file);
final AsfHeader result = FULL_READER.read(Utils.readGUID(stream),
stream, 0);
stream.close();
return result;
}
/**
* This method tries to extract a full ASF-header out of the given stream. <br>
* If no header could be extracted <code>null</code> is returned. <br>
*
* @param file
* File which contains the ASF header.
* @return AsfHeader-Wrapper, or <code>null</code> if no supported ASF
* header was found.
* @throws IOException
* Read errors
*/
public static AsfHeader readHeader(final RandomAccessFile file)
throws IOException {
final InputStream stream = createStream(file);
return FULL_READER.read(Utils.readGUID(stream), stream, 0);
}
/**
* This method tries to extract an ASF-header out of the given stream, which
* only contains information about the audio stream.<br>
* If no header could be extracted <code>null</code> is returned. <br>
*
* @param file
* File which contains the ASF header.
* @return AsfHeader-Wrapper, or <code>null</code> if no supported ASF
* header was found.
* @throws IOException
* Read errors
*/
public static AsfHeader readInfoHeader(final RandomAccessFile file)
throws IOException {
final InputStream stream = createStream(file);
return INFO_READER.read(Utils.readGUID(stream), stream, 0);
}
/**
* This method tries to extract an ASF-header out of the given stream, which
* only contains metadata.<br>
* If no header could be extracted <code>null</code> is returned. <br>
*
* @param file
* File which contains the ASF header.
* @return AsfHeader-Wrapper, or <code>null</code> if no supported ASF
* header was found.
* @throws IOException
* Read errors
*/
public static AsfHeader readTagHeader(final RandomAccessFile file)
throws IOException {
final InputStream stream = createStream(file);
return TAG_READER.read(Utils.readGUID(stream), stream, 0);
}
/**
* Creates an instance of this reader.
*
* @param toRegister
* The chunk readers to utilize.
*
* @param readChunkOnce
* if <code>true</code>, each chunk type (identified by chunk
* GUID) will handled only once, if a reader is available, other
* chunks will be discarded.
*/
public AsfHeaderReader(final List<Class<? extends ChunkReader>> toRegister,
final boolean readChunkOnce) {
super(toRegister, readChunkOnce);
}
/**
* {@inheritDoc}
*/
public boolean canFail() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
protected AsfHeader createContainer(final long streamPosition,
final BigInteger chunkLength, final InputStream stream)
throws IOException {
final long chunkCount = Utils.readUINT32(stream);
/*
* 2 reserved bytes. first should be equal to 0x01 and second 0x02. ASF
* specification suggests to not read the content if second byte is not
* 0x02.
*/
if (stream.read() != 1) {
throw new IOException("No ASF"); //$NON-NLS-1$
}
if (stream.read() != 2) {
throw new IOException("No ASF"); //$NON-NLS-1$
}
/*
* Creating the resulting object
*/
return new AsfHeader(streamPosition, chunkLength, chunkCount);
}
/**
* {@inheritDoc}
*/
public GUID[] getApplyingIds() {
return APPLYING.clone();
}
/**
* Sets the {@link AsfExtHeaderReader}, which is to be used, when an header
* extension object is found.
*
* @param extReader
* header extension object reader.
*/
public void setExtendedHeaderReader(final AsfExtHeaderReader extReader) {
for (final GUID curr : extReader.getApplyingIds()) {
this.readerMap.put(curr, extReader);
}
}
} |