package chatroom.audio;
import chatroom.connection.Connection;
import chatroom.connection.Listener;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.SourceDataLine;
/** Audio player
*
* @author eggegg
*/
public class AudioServer extends Listener {
/** Logger */
private static final Logger logger = Logger.getLogger("Player");
/** Port pool */
private static final LinkedList<Integer> portList;
/** Initialize available list */
static {
portList = new LinkedList<Integer>();
for (int i = 3000; i < 3010; ++i) {
portList.add(i);
}
}
/** Generate port */
public static Integer getPortAssign() throws IOException {
synchronized (portList) {
if (portList.isEmpty()) {
throw new IOException();
}
return portList.poll();
}
}
/** Get an instanse */
public static AudioServer getInstance() throws IOException {
return new AudioServer(getPortAssign());
}
/** Audio mixer */
private AudioMixer mixer;
/** Mixer runner */
private MixingThread mixerRunner;
/** Input stream list */
private final List<MyAudioInputStream> audioList;
/** Data line info */
private Info info;
/** Port number */
private int port;
/** Recording flag */
private boolean flag;
/** user number */
private int userNum = 0;
/** Initialize an audio player */
public AudioServer(int assignedPort) throws IOException {
super(assignedPort);
port = assignedPort;
info = new Info(SourceDataLine.class, AudioConfig.audioFormat);
audioList = new LinkedList<MyAudioInputStream>();
mixer = new AudioMixer(AudioConfig.audioFormat, audioList);
mixerRunner = new MixingThread();
}
public void startServer() {
flag = true;
mixerRunner.start();
start();
}
public void stopServer() {
flag = false;
mixer.end();
end();
portList.add(port);
}
public boolean isStopped() {
return flag == false;
}
public int getPort() {
return port;
}
/** Catch incoming audio connection */
@Override
public void onConnection(SocketChannel channel) throws IOException {
PipedInputStream is = new PipedInputStream();
final PipedOutputStream os = new PipedOutputStream(is);
userNum++;
Connection cnt = new Connection(channel) {
@Override
protected void onRead(byte[] data, int size) {
try {
os.write(data, 0, size);
os.flush();
} catch (IOException ex) {
logger.info("Audio reading error");
}
}
@Override
public void end() {
super.end();
try {
os.close();
} catch (IOException ex) {
Logger.getLogger(AudioServer.class.getName()).log(Level.SEVERE, null, ex);
}
userNum--;
if (userNum == 0) {
logger.info("Audio server closing...");
stopServer();
}
}
};
synchronized (audioList) {
audioList.add(new MyAudioInputStream(is, AudioConfig.audioFormat, AudioSystem.NOT_SPECIFIED, cnt));
}
cnt.start();
}
private class MixingThread extends Thread {
@Override
public void run() {
while (flag) {
try {
mixer.broadcast();
} catch (IOException ex) {
logger.warning("Mixer error");
}
}
}
}
public static void main(String args[]) {
try {
AudioServer server = new AudioServer(AudioConfig.port);
server.startServer();
} catch (IOException ex) {
logger.severe("cannot create audio server");
}
}
}