package uk.co.mmscomputing.sound.provider;
import java.util.*;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.Control;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import uk.co.mmscomputing.concurrent.*;
public class Mixer implements javax.sound.sampled.Mixer{
static final AudioFormat format = new AudioFormat(8000,16,1,true,false);
// static final AudioFormat format = new AudioFormat(44100,16,2,true,false);
static final int bufSize=512;
static final int MAXLINES=32;
static private boolean isopen=false;
static private Line.Info lineinfo=null;
static private Mixer.Info mixerinfo=null;
static private DataLine[] targets=null; // in
static private DataLine[] sources=null; // out
static private Line.Info[] targetInfos=null;
static private Line.Info[] sourceInfos=null;
static private Control[] controls=new Control[0]; // no controls available
static private Vector listeners=null;
static private long position=0;
public Mixer(){
super();
}
// Line interface
public Line.Info getLineInfo(){
return lineinfo;
}
public void open(){
isopen=true;
fireListenerUpdate(LineEvent.Type.OPEN);
}
public void close(){
isopen=false;
fireListenerUpdate(LineEvent.Type.CLOSE);
}
public boolean isOpen(){
return isopen;
}
public Control[] getControls(){
return controls;
}
public boolean isControlSupported(Control.Type control){
for(int i=0; i<controls.length; i++){
if(controls[i].getType().equals(control)){
return true;
}
}
return false;
}
public Control getControl(Control.Type control){
for(int i=0; i<controls.length; i++){
if(controls[i].getType().equals(control)){
return controls[i];
}
}
throw new IllegalArgumentException(getClass().getName()+".getControl:\n\tIllegal Argument.\n\t"+control);
}
public void addLineListener(LineListener listener){
listeners.add(listener);
}
public void removeLineListener(LineListener listener){
listeners.remove(listener);
}
public void fireListenerUpdate(LineEvent.Type type){
for(Enumeration e = listeners.elements(); e.hasMoreElements() ;){
LineListener listener=(LineListener)e.nextElement();
listener.update(new LineEvent(this,type,position));
}
}
// Mixer Interface
public javax.sound.sampled.Mixer.Info getMixerInfo(){
return mixerinfo;
}
public Line.Info[] getSourceLineInfo(){
return sourceInfos;
}
public Line.Info[] getTargetLineInfo(){
return targetInfos;
}
public Line.Info[] getSourceLineInfo(Line.Info info){
for(int i=0; i<sourceInfos.length; i++){
if(info.matches(sourceInfos[i])){
return sourceInfos;
}
}
return new Line.Info[0];
}
public Line.Info[] getTargetLineInfo(Line.Info info){
for(int i=0; i<targetInfos.length; i++){
if(info.matches(targetInfos[i])){
return targetInfos;
}
}
return new Line.Info[0];
}
public boolean isLineSupported(Line.Info info){
for(int i=0; i<sourceInfos.length; i++){
if(info.matches(sourceInfos[i])){
return true;
}
}
for(int i=0; i<targetInfos.length; i++){
if(info.matches(targetInfos[i])){
return true;
}
}
return false;
}
public Line getLine(Line.Info info)throws LineUnavailableException{
for(int i=0; i<targetInfos.length; i++){
if(info.matches(targetInfos[i])){
DataLine line=targets[i];
if(!line.isOpen()){
return line;
}
}
}
for(int i=0; i<sourceInfos.length; i++){
if(info.matches(sourceInfos[i])){
DataLine line=sources[i];
if(!line.isOpen()){
return line;
}
}
}
throw new LineUnavailableException(getClass().getName()+".getLine:\n\tLine Unavailable\n\t"+info);
}
public int getMaxLines(Line.Info info){
int maxlines=0;
for(int i=0; i<targetInfos.length; i++){
if(info.matches(targetInfos[i])){maxlines++;}
}
for(int i=0; i<sourceInfos.length; i++){
if(info.matches(sourceInfos[i])){maxlines++;}
}
return maxlines;
}
public Line[] getSourceLines(){
return sources;
}
public Line[] getTargetLines(){
return targets;
}
public void synchronize(Line[] lines,boolean maintainSync){
throw new IllegalArgumentException();
}
public void unsynchronize(Line[] lines){
throw new IllegalArgumentException();
}
public boolean isSynchronizationSupported(Line[] lines,boolean maintainSync){
return false;
}
static public javax.sound.sampled.Mixer.Info getMixerInfoDesc(){
return mixerinfo;
}
static{
mixerinfo=new Info(
"uk.co.mmscomputing.sound.provider.Mixer",
"mm's computing",
"Virtual mixer offering multiple default input/output lines.",
"2005-03-12"
);
lineinfo=new Line.Info(Mixer.class);
// String osname=System.getProperty("os.name");java.runtime.version
String javaversion=System.getProperty("java.runtime.version");// does not work with anything before 1.5
// System.out.println("java.runtime.version : "+javaversion);
// if(javaversion.startsWith("1.5")/*||javaversion.startsWith("1.4")*/){
sources=new DataLine[MAXLINES<<1];
sourceInfos=new Line.Info[MAXLINES<<1];
for(int i=0;i<MAXLINES;i++){
sources[i]=new SourceDataLine();
sourceInfos[i]=sources[i].getLineInfo();
}
for(int i=MAXLINES;i<(MAXLINES<<1);i++){
sources[i]=new Clip();
sourceInfos[i]=sources[i].getLineInfo();
}
try{
new SpeakerThread(sources).start();
}catch(Exception e){
e.printStackTrace();
sources=new DataLine[0];
sourceInfos=new Line.Info[0];
}
targets=new DataLine[MAXLINES];
targetInfos=new Line.Info[MAXLINES];
for(int i=0;i<MAXLINES;i++){
targets[i]=new TargetDataLine();
targetInfos[i]=targets[i].getLineInfo();
}
try{
new MicrophoneThread(targets).start();
}catch(Exception e){
e.printStackTrace();
targets=new DataLine[0];
targetInfos=new Line.Info[0];
}
/*
}else{
sources=new DataLine[0];
sourceInfos=new Line.Info[0];
targets=new DataLine[0];
targetInfos=new Line.Info[0];
}
*/
}
/*
Info class
*/
static protected class Info extends javax.sound.sampled.Mixer.Info{
protected Info(String name,String vendor,String description,String version){
super(name,vendor,description,version);
}
}
}