/*
* File: $HeadURL: https://jsapi.svn.sourceforge.net/svnroot/jsapi/trunk/org.jvoicexml.jsapi2.jse/src/org/jvoicexml/jsapi2/jse/protocols/capture/CaptureURLConnection.java $
* Version: $LastChangedRevision: 288 $
* Date: $LastChangedDate $
* Author: $LastChangedBy: schnelle $
*
* JSAPI - An base implementation for JSR 113.
*
* Copyright (C) 2009 JVoiceXML group - http://jvoicexml.sourceforge.net
*
*/
package net.sourceforge.gjtapi.protocols.capture;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.UnknownServiceException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.Mixer.Info;
import net.sourceforge.gjtapi.protocols.JavaSoundParser;
/**
* A {@link URLConnection} for the capture protool.
* @author Renato Cassaca
* @author Dirk Schnelle-Walka
* @version 1.0
*/
public class CaptureURLConnection extends URLConnection {
/** Device that that this URLConnection will connect to. */
private final String deviceName;
/** The audio format to use. */
private AudioFormat audioFormat;
/** The current line. */
private TargetDataLine line;
/** The audio input stream. */
private AudioInputStream inputStream;
/**
* Constructs a new object.
*
* @param url
* URL
*/
public CaptureURLConnection(final URL url) {
super(url);
// Initialize the device that will be connecting to
try {
final String authority = url.getAuthority();
deviceName = URLDecoder.decode(authority, "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new UnsupportedOperationException(ex);
}
}
/**
* {@inheritDoc}
*
* Closes any open line.
*/
protected void finalize() throws Throwable {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignore) {
}
inputStream = null;
}
if (line != null) {
if (line.isOpen()) {
line.close();
}
line = null;
}
}
/**
* Opens a communications link to the resource referenced by this URL, if
* such a connection has not already been established.
*
* @throws IOException
* if an I/O error occurs while opening the connection.
* @todo Implement this java.net.URLConnection method
*/
public synchronized void connect() throws IOException {
if (connected) {
return;
}
// Get the mixer info associated with the device name
line = getLine();
if (line == null) {
throw new IOException("Cannot open line with required format: "
+ getAudioFormat());
}
// Obtain, open and start the line.
try {
line.open(audioFormat, AudioSystem.NOT_SPECIFIED);
// Starts the line
line.start();
} catch (LineUnavailableException ex) {
throw new IOException("Line is unavailable");
}
// Marks this URLConnection as connected
connected = true;
}
/**
* Retrieves the line to use.
*
* @return the line to use.
* @exception IOException
* error obtaining the line.
*/
private TargetDataLine getLine() throws IOException {
if (deviceName.equals("audio")) {
try {
line = AudioSystem.getTargetDataLine(getAudioFormat());
} catch (LineUnavailableException ex) {
ex.printStackTrace();
return null;
}
} else {
// Get the mixer info for the device
Info mixerInfo = getMixerInfo();
if (mixerInfo == null) {
return null;
}
Mixer mixer = AudioSystem.getMixer(mixerInfo);
try {
mixer.open();
} catch (LineUnavailableException ex1) {
ex1.printStackTrace();
}
Line[] liness = mixer.getTargetLines();
for (Line lll : liness) {
System.out.println("Infos: " + lll);
}
// Info[] infos = AudioSystem.getTargetLineInfo(mixerInfo);
DataLine.Info lineInfo = new DataLine.Info(TargetDataLine.class,
getAudioFormat());
try {
line = (TargetDataLine) mixer.getLine(lineInfo);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
return null;
}
}
return line;
}
/**
* Given a mixer name, returns the mixer info that matches.
*
* @return Info
*/
private Info getMixerInfo() {
Info[] mixerInfo = AudioSystem.getMixerInfo();
for (Info info : mixerInfo) {
if (info.getName().contains(deviceName)) {
if (!info.getName().contains("Playback")
&& !info.getDescription().contains("Playback")) {
return info;
}
}
}
return null;
}
/**
* Given URI parameters, constructs an AudioFormat.
*
* @return AudioFormat
* @exception IOException
* error determining the audio format.
*/
public AudioFormat getAudioFormat() throws IOException {
if (audioFormat == null) {
final URL url = getURL();
try {
audioFormat = JavaSoundParser.parse(url);
} catch (URISyntaxException e) {
throw new IOException(e.getMessage());
}
}
return audioFormat;
}
/**
* {@inheritDoc}
*/
public InputStream getInputStream() throws IOException {
// Get line associated with connection
if (line == null) {
throw new IOException("Not connected to line");
}
// Setup the input stream
if (inputStream == null) {
inputStream = new AudioInputStream(line);
}
return inputStream;
}
/**
* {@inheritDoc}
* Throws an {@link UnknownServiceException}.
*
* @throws UnknownServiceException
* output streams are not supported by the capture protocol.
*/
public OutputStream getOutputStream() throws UnknownServiceException {
throw new UnknownServiceException("Cannot write to a capture device");
}
}