public class IcyInputStream extends BufferedInputStream
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.
| Modifier and Type | Field and Description |
|---|---|
protected int |
bytesUntilNextMetadata
how many bytes of real data remain before the next
block of metadata.
|
protected byte[] |
crlfBuffer
Buffer for readCRLF line... note this limits lines to
1024 chars (I've read that WinAmp barfs at 128, so
this is generous)
|
protected static 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.
|
in| Constructor and Description |
|---|
IcyInputStream(InputStream in)
Reads the initial headers of the stream and adds
tags appropriatly.
|
IcyInputStream(InputStream in,
String metaIntString,
TagParseListener listener)
IcyInputStream constructor for know meta-interval (Icecast 2)
|
IcyInputStream(InputStream in,
TagParseListener listener)
Reads the initial headers of the stream and adds
tags appropriatly.
|
| Modifier and Type | Method and Description |
|---|---|
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 a stream parses MP3Tags.
|
void |
fireTagParsed(Object source,
IcyTag tag) |
void |
fireTagParseEvent(TagParseEvent tpe)
Fires the given event to all registered listeners
|
IcyTag |
getTag(String tagName)
Get the named tag from the HashMap of headers and
in-line tags.
|
HashMap<String,IcyTag> |
getTagHash()
Returns a HashMap of all headers and in-stream tags
parsed so far.
|
IcyTag[] |
getTags()
Get all tags (headers or in-stream) encountered thus far.
|
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 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 a stream parses MP3Tags.
|
available, close, mark, markSupported, reset, skipprotected static final String INLINE_TAG_SEPARATORS
protected byte[] crlfBuffer
protected int metaint
protected int bytesUntilNextMetadata
public IcyInputStream(InputStream in, String metaIntString, TagParseListener listener) throws IOException
in - metaint - IOExceptionpublic IcyInputStream(InputStream in) throws IOException
icy-metaint header is found.IOExceptionpublic IcyInputStream(InputStream in, TagParseListener listener) throws IOException
icy-metaint header is found.IOExceptionprotected void readInitialHeaders()
throws IOException
IOExceptionprotected String readCRLFLine() throws IOException
IOExceptionpublic int read()
throws IOException
read in class BufferedInputStreamIOExceptionpublic int read(byte[] buf,
int offset,
int length)
throws IOException
bytesUntilNextMetadata < lengthread in class BufferedInputStreamIOExceptionpublic int read(byte[] buf)
throws IOException
return read (buf, 0, buf.length)read in class FilterInputStreamIOExceptionprotected void readMetadata()
throws IOException
IOExceptionprotected 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 IcyTag getTag(String tagName)
public IcyTag[] getTags()
public HashMap<String,IcyTag> getTagHash()
public void addTagParseListener(TagParseListener tpl)
public void removeTagParseListener(TagParseListener tpl)
public void fireTagParseEvent(TagParseEvent tpe)
Copyright © 2014. All rights reserved.