/*
* Entagged Audio Tag library
* Copyright (c) 2003-2005 Raphaƫl Slinckx <raphael@slinckx.net>
*
* 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.tag.mp4;
import org.jaudiotagger.audio.generic.AbstractTagCreator;
import org.jaudiotagger.audio.generic.Utils;
import org.jaudiotagger.audio.mp4.Mp4NotMetaFieldKey;
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.KeyNotFoundException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagField;
import org.jaudiotagger.tag.mp4.field.Mp4TagCoverField;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Iterator;
/**
* Create raw content of mp4 tag data, concerns itself with atoms upto the ilst atom
* <p/>
* <p>This level is was selected because the ilst atom can be recreated without reference to existing mp4 fields
* but fields above this level are dependent upon other information that is not held in the tag.
* <p/>
* <pre>
* |--- ftyp
* |--- moov
* |......|
* |......|----- mvdh
* |......|----- trak
* |......|----- udta
* |..............|
* |..............|-- meta
* |....................|
* |....................|-- hdlr
* |....................|-- ilst
* |....................|.. ..|
* |....................|.....|---- @nam (Optional for each metadatafield)
* |....................|.....|.......|-- data
* |....................|.....|....... ecetera
* |....................|.....|---- ---- (Optional for reverse dns field)
* |....................|.............|-- mean
* |....................|.............|-- name
* |....................|.............|-- data
* |....................|................ ecetere
* |....................|-- free
* |--- free
* |--- mdat
* </pre>
*/
public class Mp4TagCreator extends AbstractTagCreator {
/**
* Convert tagdata to rawdata ready for writing to file
*
* @param tag
* @param padding TODO padding parameter currently ignored
* @return
* @throws UnsupportedEncodingException
*/
public ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException {
try {
//Add metadata raw content
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Iterator<TagField> it = tag.getFields();
boolean processedArtwork = false;
while (it.hasNext()) {
TagField frame = it.next();
//To ensure order is maintained dont process artwork until iterator hits it.
if (frame instanceof Mp4TagCoverField) {
if (processedArtwork) {
//ignore
} else {
processedArtwork = true;
//Because each artwork image is held within the tag as a seperate field, but when
//they are written they are all held under a single covr box we need to do some checks
//and special processing here if we have any artwork image (this code only neccessary
//if we have more than 1 but do it anyway even if only have 1 image)
ByteArrayOutputStream covrDataBaos = new ByteArrayOutputStream();
try {
for (TagField artwork : tag.getFields(FieldKey.COVER_ART)) {
covrDataBaos.write(((Mp4TagField) artwork).getRawContentDataOnly());
}
} catch (KeyNotFoundException knfe) {
//This cannot happen
throw new RuntimeException("Unable to find COVERART Key");
}
//Now create the parent Data
byte[] data = covrDataBaos.toByteArray();
baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + data.length));
baos.write(Utils.getDefaultBytes(Mp4FieldKey.ARTWORK.getFieldName(), "ISO-8859-1"));
baos.write(data);
}
} else {
baos.write(frame.getRawContent());
}
}
//Wrap into ilst box
ByteArrayOutputStream ilst = new ByteArrayOutputStream();
ilst.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
ilst.write(Utils.getDefaultBytes(Mp4NotMetaFieldKey.ILST.getFieldName(), "ISO-8859-1"));
ilst.write(baos.toByteArray());
//Put into ByteBuffer
ByteBuffer buf = ByteBuffer.wrap(ilst.toByteArray());
buf.rewind();
return buf;
} catch (IOException ioe) {
//Should never happen as not writing to file at this point
throw new RuntimeException(ioe);
}
}
}