/* * 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; } }