
org.blinkenlights.jid3.v2.ETCOID3V2Frame Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of JID3 Show documentation
Show all versions of JID3 Show documentation
JID3 is a class library, written in Java and licensed under the LGPL, which provides the required functionality for editing ID3 tags commonly used in MP3 media files.
The newest version!
/*
* ETCOID3V2Frame.java
*
* Created on Jan 31, 2004
*
* Copyright (C)2004,2005 Paul Grebenc
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: ETCOID3V2Frame.java,v 1.10 2005/02/06 18:11:15 paul Exp $
*/
package org.blinkenlights.jid3.v2;
import java.io.*;
import java.util.*;
import org.blinkenlights.jid3.*;
import org.blinkenlights.jid3.io.*;
import org.blinkenlights.jid3.util.*;
/**
* @author paul
*
* Frame containing event timing codes.
*/
public class ETCOID3V2Frame extends ID3V2Frame
{
private TimestampFormat m_oTimestampFormat;
private SortedMap m_oTimeToEventMap = null;
/** Constructor.
*
* @param oTimestampFormat the format for timestamps, whether by millisecond or frame count
* @throws ID3Exception if oTimestampFormat object is null
*/
public ETCOID3V2Frame(TimestampFormat oTimestampFormat)
throws ID3Exception
{
if (oTimestampFormat == null)
{
throw new ID3Exception("Timestamp format required in ETCO frame.");
}
m_oTimestampFormat = oTimestampFormat;
m_oTimeToEventMap = new TreeMap();
}
public ETCOID3V2Frame(InputStream oIS)
throws ID3Exception
{
// Parse out the text encoding and text string from the raw data
try
{
ID3DataInputStream oFrameDataID3DIS = new ID3DataInputStream(oIS);
// timestamp format
m_oTimestampFormat = new TimestampFormat((byte)oFrameDataID3DIS.readUnsignedByte());
// read events and timestamps to end
m_oTimeToEventMap = new TreeMap();
while (oFrameDataID3DIS.available() > 0)
{
byte byTypeOfEvent = (byte)oFrameDataID3DIS.readUnsignedByte();
EventType oEventType = new EventType(byTypeOfEvent);
int iTimestamp = oFrameDataID3DIS.readBE32();
addEvent(new Event(oEventType, iTimestamp));
}
}
catch (Exception e)
{
throw new InvalidFrameID3Exception(e);
}
}
public void accept(ID3Visitor oID3Visitor)
{
oID3Visitor.visitETCOID3V2Frame(this);
}
/** Get the set timestamp format.
*
* @return the currently set timestamp format
*/
public TimestampFormat getTimestampFormat()
{
return m_oTimestampFormat;
}
/** Add an event to the list. Note, only one event per exact time can be defined. An event set at
* a time for which another event already is set will overwrite the existing one.
*
* @param oEvent the event being set
*/
public void addEvent(Event oEvent)
{
m_oTimeToEventMap.put(new Integer(oEvent.getTimestamp()), oEvent);
}
/** Get the event which has been set for a given time.
*
* @return the event set for the given time, or null if no event has been set for that time
* @throws ID3Exception if the timestamp specified is negative
*/
public Event getEvent(int iTimestamp)
throws ID3Exception
{
if (iTimestamp < 0)
{
throw new ID3Exception("Negative timestamps are not valid in ETCO frames.");
}
return (Event)m_oTimeToEventMap.get(new Integer(iTimestamp));
}
/** Get all events which have been set. Events are returned in sorted order by timestamp.
*
* @return an array of Events which have been set
*/
public Event[] getEvents()
{
return (Event[])m_oTimeToEventMap.values().toArray(new Event[0]);
}
/** Remove the event set for a specific time.
*
* @return the event which was previously set for the given time, or null if no even was set for that time
*/
public Event removeEvent(Event oEvent)
{
return (Event)m_oTimeToEventMap.remove(new Integer(oEvent.getTimestamp()));
}
protected byte[] getFrameId()
{
return "ETCO".getBytes();
}
public String toString()
{
StringBuffer sbOutput = new StringBuffer();
sbOutput.append("Event Timing Codes: Timestamp format = " + m_oTimestampFormat.getValue());
sbOutput.append(", Events = ");
Iterator oIter = m_oTimeToEventMap.values().iterator();
while (oIter.hasNext())
{
Event oEvent = (Event)oIter.next();
sbOutput.append(oEvent.getEventType().getValue() + ":" + oEvent.getTimestamp() + " ");
}
return sbOutput.toString();
}
protected void writeBody(ID3DataOutputStream oIDOS)
throws IOException
{
// timestamp format
oIDOS.writeUnsignedByte(m_oTimestampFormat.getValue());
// events
Iterator oIter = m_oTimeToEventMap.values().iterator();
while (oIter.hasNext())
{
Event oEvent = (Event)oIter.next();
oIDOS.writeUnsignedByte(oEvent.getEventType().getValue());
oIDOS.writeBE32(oEvent.getTimestamp());
}
}
/** Timestamp format. The timestamp format is used to specify how offsets from the start of the
* the file are measured for events.
*/
public static class TimestampFormat
{
private byte m_byTimestampFormat;
private TimestampFormat(byte byTimestampFormat)
{
m_byTimestampFormat = byTimestampFormat;
}
private byte getValue()
{
return m_byTimestampFormat;
}
/** Timestamp format indicating that timestamps are measured in MPEG frames from the start of the file. */
public static final TimestampFormat ABSOLUTE_MPEG_FRAMES = new TimestampFormat((byte)0x01);
/** Timestamp format indicating that timestamps are measured in milliseconds from the start of the file. */
public static final TimestampFormat ABSOLUTE_MILLISECONDS = new TimestampFormat((byte)0x02);
public boolean equals(Object oOther)
{
try
{
TimestampFormat oOtherTF = (TimestampFormat)oOther;
return (m_byTimestampFormat == oOtherTF.m_byTimestampFormat);
}
catch (Exception e)
{
return false;
}
}
}
/** Event types. */
public static class EventType
{
private byte m_byTypeOfEvent;
private EventType(byte byTypeOfEvent)
{
m_byTypeOfEvent = byTypeOfEvent;
}
private byte getValue()
{
return m_byTypeOfEvent;
}
/** Pre-defined event types. */
public static final EventType PADDING = new EventType((byte)0x00);
public static final EventType END_OF_INITIAL_SILENCE = new EventType((byte)0x01);
public static final EventType INTRO_START = new EventType((byte)0x02);
public static final EventType MAINPART_START = new EventType((byte)0x03);
public static final EventType OUTRO_START = new EventType((byte)0x04);
public static final EventType OUTRO_END = new EventType((byte)0x05);
public static final EventType VERSE_START = new EventType((byte)0x06);
public static final EventType REFRAIN_START = new EventType((byte)0x07);
public static final EventType INTERLUDE_START = new EventType((byte)0x08);
public static final EventType THEME_START = new EventType((byte)0x09);
public static final EventType VARIATION_START = new EventType((byte)0x0a);
public static final EventType KEY_CHANGE = new EventType((byte)0x0b);
public static final EventType TIME_CHANGE = new EventType((byte)0x0c);
public static final EventType MOMENTARY_UNWANTED_NOISE = new EventType((byte)0x0d);
public static final EventType SUSTAINED_NOISE = new EventType((byte)0x0e);
public static final EventType SUSTAINED_NOISE_END = new EventType((byte)0x0f);
public static final EventType INTRO_END = new EventType((byte)0x10);
public static final EventType MAINPART_END = new EventType((byte)0x11);
public static final EventType VERSE_END = new EventType((byte)0x12);
public static final EventType REFRAIN_END = new EventType((byte)0x13);
public static final EventType THEME_END = new EventType((byte)0x14);
public static final EventType USER_DEFINED_01 = new EventType((byte)0xe0);
public static final EventType USER_DEFINED_02 = new EventType((byte)0xe1);
public static final EventType USER_DEFINED_03 = new EventType((byte)0xe2);
public static final EventType USER_DEFINED_04 = new EventType((byte)0xe3);
public static final EventType USER_DEFINED_05 = new EventType((byte)0xe4);
public static final EventType USER_DEFINED_06 = new EventType((byte)0xe5);
public static final EventType USER_DEFINED_07 = new EventType((byte)0xe6);
public static final EventType USER_DEFINED_08 = new EventType((byte)0xe7);
public static final EventType USER_DEFINED_09 = new EventType((byte)0xe8);
public static final EventType USER_DEFINED_10 = new EventType((byte)0xe9);
public static final EventType USER_DEFINED_11 = new EventType((byte)0xea);
public static final EventType USER_DEFINED_12 = new EventType((byte)0xeb);
public static final EventType USER_DEFINED_13 = new EventType((byte)0xec);
public static final EventType USER_DEFINED_14 = new EventType((byte)0xed);
public static final EventType USER_DEFINED_15 = new EventType((byte)0xee);
public static final EventType USER_DEFINED_16 = new EventType((byte)0xef);
public static final EventType AUDIO_END = new EventType((byte)0xfd);
public static final EventType AUDIO_FILE_ENDS = new EventType((byte)0xfe);
//NOTE: $FF seems to be defined in the spec, but I do not understand the definition...
public boolean equals(Object oOther)
{
try
{
EventType oOtherET = (EventType)oOther;
return (m_byTypeOfEvent == oOtherET.m_byTypeOfEvent);
}
catch (Exception e)
{
return false;
}
}
}
/** Event. Events are comprised of a timestamp, and a type of event indicated for that time. */
public static class Event
{
private EventType m_oEventType;
private int m_iTimestamp;
/** Constructor.
*
* @param oEventType the type of event to be indicated
* @param iTimestamp the time of the event, specified in the chosen format
* @throws ID3Exception if the timestamp value is negative
*/
public Event(EventType oEventType, int iTimestamp)
throws ID3Exception
{
if (iTimestamp < 0)
{
throw new ID3Exception("Negative timestamps are not valid in ETCO frames.");
}
m_oEventType = oEventType;
m_iTimestamp = iTimestamp;
}
/** Get the type of event specified.
*
* @return the type of event specified
*/
public EventType getEventType()
{
return m_oEventType;
}
/** Get the timestamp for this event.
*
* @return the timestamp for this event, to be interpreted in the current chosen format
*/
public int getTimestamp()
{
return m_iTimestamp;
}
public boolean equals(Object oOther)
{
try
{
Event oOtherEvent = (Event)oOther;
return ((m_iTimestamp == oOtherEvent.m_iTimestamp) &&
m_oEventType.equals(oOtherEvent.m_oEventType));
}
catch (Exception e)
{
return false;
}
}
}
public boolean equals(Object oOther)
{
if ((oOther == null) || (!(oOther instanceof ETCOID3V2Frame)))
{
return false;
}
ETCOID3V2Frame oOtherETCO = (ETCOID3V2Frame)oOther;
return (m_oTimestampFormat.equals(oOtherETCO.m_oTimestampFormat) &&
m_oTimeToEventMap.equals(oOtherETCO.m_oTimeToEventMap));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy