/*
* 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,
* you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jaudiotagger.tag.datatype;
import org.jaudiotagger.tag.InvalidDataTypeException;
import org.jaudiotagger.tag.id3.AbstractTagFrameBody;
import org.jaudiotagger.tag.id3.valuepair.EventTimingTypes;
/**
* A single event timing code. Part of a list of timing codes ({@link EventTimingCodeList}), that are contained in
* {@link org.jaudiotagger.tag.id3.framebody.FrameBodyETCO}.
*
* @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
* @version $Id:$
*/
public class EventTimingCode extends AbstractDataType implements Cloneable
{
private static final int SIZE = 5;
private NumberHashMap type = new NumberHashMap(DataTypes.OBJ_TYPE_OF_EVENT, null, 1);
private NumberFixedLength timestamp = new NumberFixedLength(DataTypes.OBJ_DATETIME, null, 4);
public EventTimingCode(final EventTimingCode copy) {
super(copy);
this.type.setValue(copy.type.getValue());
this.timestamp.setValue(copy.timestamp.getValue());
}
public EventTimingCode(final String identifier, final AbstractTagFrameBody frameBody)
{
this(identifier, frameBody, 0x00, 0L);
}
public EventTimingCode(final String identifier, final AbstractTagFrameBody frameBody, final int type, final long timestamp)
{
super(identifier, frameBody);
setBody(frameBody);
this.type.setValue(type);
this.timestamp.setValue(timestamp);
}
@Override
public void setBody(final AbstractTagFrameBody frameBody)
{
super.setBody(frameBody);
this.type.setBody(frameBody);
this.timestamp.setBody(frameBody);
}
public long getTimestamp()
{
return ((Number)timestamp.getValue()).longValue();
}
public void setTimestamp(final long timestamp)
{
this.timestamp.setValue(timestamp);
}
public int getType()
{
return ((Number) type.getValue()).intValue();
}
public void setType(final int type)
{
this.type.setValue(type);
}
@Override
public int getSize()
{
return SIZE;
}
@Override
public void readByteArray(final byte[] buffer, final int originalOffset) throws InvalidDataTypeException
{
int localOffset = originalOffset;
int size = getSize();
logger.finest("offset:" + localOffset);
//The read has extended further than the defined frame size (ok to extend upto
//size because the next datatype may be of length 0.)
if (originalOffset > buffer.length-size)
{
logger.warning("Invalid size for FrameBody");
throw new InvalidDataTypeException("Invalid size for FrameBody");
}
this.type.readByteArray(buffer, localOffset);
localOffset += this.type.getSize();
this.timestamp.readByteArray(buffer, localOffset);
localOffset += this.timestamp.getSize();
}
@Override
public byte[] writeByteArray()
{
final byte[] typeData = this.type.writeByteArray();
final byte[] timeData = this.timestamp.writeByteArray();
if (typeData == null || timeData == null) return null;
final byte[] objectData = new byte[typeData.length + timeData.length];
System.arraycopy(typeData, 0, objectData, 0, typeData.length);
System.arraycopy(timeData, 0, objectData, typeData.length, timeData.length);
return objectData;
}
@Override
public boolean equals(final Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
final EventTimingCode that = (EventTimingCode) o;
if (this.getType() != that.getType() || this.getTimestamp() != that.getTimestamp()) return false;
return true;
}
@Override
public int hashCode()
{
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "" + getType() + " (\"" + EventTimingTypes.getInstanceOf().getValueForId(getType()) + "\"), " + getTimestamp();
}
@Override
public Object clone() throws CloneNotSupportedException {
return new EventTimingCode(this);
}
}