|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectjava.io.InputStream
java.io.FilterInputStream
java.io.BufferedInputStream
javazoom.spi.mpeg.sampled.file.tag.IcyInputStream
public class IcyInputStream
An BufferedInputStream that parses Shoutcast's "icy" metadata from the stream. Gets headers at the beginning and if the "icy-metaint" tag is found, it parses and strips in-stream metadata.
The deal with metaint: Icy streams don't try to put
tags between MP3 frames the way that ID3 does. Instead, it
requires the client to strip metadata from the stream before
it hits the decoder. You get an
icy-metaint
name/val in the beginning of the
stream iff you sent "Icy-Metadata" with value "1" in the
request headers (SimpleMP3DataSource does this if the
"parseStreamMetadata" boolean is true). If this is the case
then the value of icy-metaint is the amount of real data
between metadata blocks. Each block begins with an int
indicating how much metadata there is -- the block is this
value times 16 (it can be, and often is, 0).
Originally thought that "icy" implied Icecast, but this is completely wrong -- real Icecast servers, found through www.icecast.net and typified by URLs with a trailing directory (like CalArts School of Music - http://65.165.174.100:8000/som) do not have the "ICY 200 OK" magic string or any of the CRLF-separated headers. Apparently, "icy" means "Shoutcast". Yep, that's weird.
Field Summary | |
---|---|
protected int |
bytesUntilNextMetadata
how many bytes of real data remain before the next block of metadata. |
protected byte[] |
crlfBuffer
Buffer for readCRLF line... |
static boolean |
DEBUG
|
protected static java.lang.String |
INLINE_TAG_SEPARATORS
inline tags are delimited by ';', also filter out null bytes |
protected int |
metaint
value of the "metaint" tag, which tells us how many bytes of real data are between the metadata tags. |
Fields inherited from class java.io.BufferedInputStream |
---|
buf, count, marklimit, markpos, pos |
Fields inherited from class java.io.FilterInputStream |
---|
in |
Constructor Summary | |
---|---|
IcyInputStream(java.io.InputStream in)
Reads the initial headers of the stream and adds tags appropriatly. |
|
IcyInputStream(java.io.InputStream in,
java.lang.String metaIntString)
IcyInputStream constructor for know meta-interval (Icecast 2) |
Method Summary | |
---|---|
protected void |
addTag(IcyTag tag)
adds the tag to the HashMap of tags we have encountered either in-stream or as headers, replacing any previous tag with this name. |
void |
addTagParseListener(TagParseListener tpl)
Adds a TagParseListener to be notified when this stream parses MP3Tags. |
MP3Tag |
getTag(java.lang.String tagName)
Get the named tag from the HashMap of headers and in-line tags. |
java.util.HashMap |
getTagHash()
Returns a HashMap of all headers and in-stream tags parsed so far. |
MP3Tag[] |
getTags()
Get all tags (headers or in-stream) encountered thus far. |
static void |
main(java.lang.String[] args)
Quickie unit-test. |
protected void |
parseInlineIcyTags(byte[] tagBlock)
Parse metadata from an in-stream "block" of bytes, add a tag for each one. |
int |
read()
Reads and returns a single byte. |
int |
read(byte[] buf)
trivial return read (buf, 0, buf.length) |
int |
read(byte[] buf,
int offset,
int length)
Reads a block of bytes. |
protected java.lang.String |
readCRLFLine()
Read everything up to the next CRLF, return it as a String. |
protected void |
readInitialHeaders()
Assuming we're at the top of the stream, read lines one by one until we hit a completely blank \r\n. |
protected void |
readMetadata()
Read the next segment of metadata. |
void |
removeTagParseListener(TagParseListener tpl)
Removes a TagParseListener, so it won't be notified when this stream parses MP3Tags. |
Methods inherited from class java.io.BufferedInputStream |
---|
available, close, mark, markSupported, reset, skip |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static boolean DEBUG
protected static final java.lang.String INLINE_TAG_SEPARATORS
protected byte[] crlfBuffer
protected int metaint
protected int bytesUntilNextMetadata
Constructor Detail |
---|
public IcyInputStream(java.io.InputStream in) throws java.io.IOException
icy-metaint
header is found.
java.io.IOException
public IcyInputStream(java.io.InputStream in, java.lang.String metaIntString) throws java.io.IOException
in
- metaint
-
java.io.IOException
Method Detail |
---|
protected void readInitialHeaders() throws java.io.IOException
java.io.IOException
protected java.lang.String readCRLFLine() throws java.io.IOException
java.io.IOException
public int read() throws java.io.IOException
read
in class java.io.BufferedInputStream
java.io.IOException
public int read(byte[] buf, int offset, int length) throws java.io.IOException
bytesUntilNextMetadata < length
read
in class java.io.BufferedInputStream
java.io.IOException
public int read(byte[] buf) throws java.io.IOException
return read (buf, 0, buf.length)
read
in class java.io.FilterInputStream
java.io.IOException
protected void readMetadata() throws java.io.IOException
java.io.IOException
protected void parseInlineIcyTags(byte[] tagBlock)
Hilariously, the inline data format is totally different than the top-of-stream header. For example, here's a block I saw on "Final Fantasy Radio":
StreamTitle='Final Fantasy 8 - Nobuo Uematsu - Blue Fields';StreamUrl='';In other words:
protected void addTag(IcyTag tag)
public MP3Tag getTag(java.lang.String tagName)
public MP3Tag[] getTags()
getTags
in interface MP3MetadataParser
public java.util.HashMap getTagHash()
public void addTagParseListener(TagParseListener tpl)
addTagParseListener
in interface MP3MetadataParser
public void removeTagParseListener(TagParseListener tpl)
removeTagParseListener
in interface MP3MetadataParser
public static void main(java.lang.String[] args)
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |