/*
* Copyright (C) 2005 Luca Veltri - University of Parma - Italy
*
* This source code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author(s):
* Luca Veltri (luca.veltri@unipr.it)
*/
package local.media;
import java.io.*;
import java.util.Hashtable;
import java.util.Enumeration;
/** MixerLine is a simple G711 mixer with N input lines (InputStream)
* and one output line (the MixerLine itself).
* <p/>
* Each input line has an identifier (Object) used as key when adding or
* removing the line.
*/
public class MixerLine extends InputStream
{
/** SplitterLine identifier. */
Object mixer_id;
/** The input lines (as Hashtable of Object->InputStream). */
Hashtable input_lines;
/** Creates a new MixerLine. */
public MixerLine(Object mixer_id)
{ this.mixer_id=mixer_id;
input_lines=new Hashtable();
}
/** Creates a new MixerLine. */
public MixerLine(Object mixer_id, Hashtable input_lines)
{ this.mixer_id=mixer_id;
this.input_lines=input_lines;
}
/** Adds a new line. */
public void addLine(Object id, InputStream is)
{ //System.err.println("ML: add: "+id+" "+is);
input_lines.put(id,is);
}
/** Removes a line. */
public void removeLine(Object id)
{ //System.err.println("ML: remove: "+id);
input_lines.remove(id);
}
/** Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream. */
public int available() throws IOException
{ int max=0;
for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ int n=((InputStream)e.nextElement()).available();
if (n>max) max=n;
}
return max;
}
/** Closes this input stream and releases any system resources associated with the stream. */
public void close() throws IOException
{ for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ ((InputStream)e.nextElement()).close();
}
input_lines=null;
}
/** Marks the current position in this input stream. */
public void mark(int readlimit)
{ for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ ((InputStream)e.nextElement()).mark(readlimit);
}
}
/** Tests if this input stream supports the mark and reset methods. */
public boolean markSupported()
{ boolean supported=true;
for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ if (!((InputStream)e.nextElement()).markSupported()) supported=false;
}
return supported;
}
/** Reads the next byte of data from the input stream. */
public int read() throws IOException
{ int sum=0;
int count=0;
int err_code=0;
for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ InputStream is=(InputStream)e.nextElement();
if (is.available()>0);
{ int value=is.read();
if (value>0)
{ count++;
sum+=G711.ulaw2linear(value);
}
else err_code=value;
}
}
if (count>0 || err_code==0) return G711.linear2ulaw(sum);
else return err_code;
}
/** Reads some number of bytes from the input stream and stores them into the buffer array b. */
public int read(byte[] b) throws IOException
{ //System.err.print("o");
int ret=super.read(b);
//System.err.print(".");
return ret;
}
/** Reads up to len bytes of data from the input stream into an array of bytes. */
public int read(byte[] b, int off, int len) throws IOException
{ //System.err.print("o");
int ret=super.read(b,off,len);
//System.err.print(".");
return ret;
}
/** Repositions this stream to the position at the time the mark method was last called on this input stream. */
public void reset() throws IOException
{ for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ ((InputStream)e.nextElement()).reset();
}
}
/** Skips over and discards n bytes of data from this input stream. */
public long skip(long n) throws IOException
{ for (Enumeration e=input_lines.elements(); e.hasMoreElements(); )
{ ((InputStream)e.nextElement()).skip(n);
}
return n;
}
}