/*
* File : FalseClip.java
* Created : 04-aug-2004 16:26
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* This program 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 program 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 (see the LICENSE file).
*/
package edu.xtec.jclic.media;
import edu.xtec.jclic.bags.MediaBag;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.08.28
*/
public class FalseClip implements PseudoClip{
private AudioInputStream ais;
private AudioFormat af;
private MediaBag mb;
private String mediaFileName;
private PlayThread playThread;
private int loopCount;
/** Creates a new instance of FalseClip */
private FalseClip(MediaBag mb, String mediaFileName) throws Exception {
this.mb=mb;
this.mediaFileName=mediaFileName;
af=getAudioInputStream().getFormat();
}
public static FalseClip getFalseClip(MediaBag mb, String mediaFileName) throws Exception{
return new FalseClip(mb, mediaFileName);
}
private AudioInputStream getAudioInputStream() throws Exception{
if(ais==null){
JavaSoundAudioPlayer jsap=new JavaSoundAudioPlayer();
jsap.setDataSource(mb.getMediaDataSource(mediaFileName));
ais=jsap.ais;
if(ais==null)
throw new Exception("Unable to open audio data!");
}
return ais;
}
public void close() {
stop();
}
public javax.sound.sampled.AudioFormat getFormat() {
return af;
}
public boolean isActive() {
return (playThread!=null && playThread.isAlive());
}
public boolean isOpen() {
return ais!=null;
}
public boolean isRunning() {
return isActive();
}
public void loop(int count) throws Exception{
start();
loopCount=count;
}
public void open() throws Exception {
getAudioInputStream();
}
public void setFramePosition(int frames) {
// ignore
}
public void setLoopPoints(int start, int end) {
// ignore
}
public void start() throws Exception{
if(playThread==null){
loopCount=0;
playThread=new PlayThread();
playThread.start();
}
}
public void stop() {
if(playThread!=null){
if(playThread.isAlive()){
playThread.running=false;
while(playThread!=null){
Thread.yield();
}
}
else{
playThread=null;
ais=null;
}
}
}
class PlayThread extends Thread {
public boolean running;
byte[] buf=new byte[JavaSoundAudioPlayer.INTERNAL_BUFFER_SIZE];
SourceDataLine line = null;
public PlayThread() throws Exception{
running=false;
getAudioInputStream();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
line = (SourceDataLine)AudioSystem.getLine(info);
if(line!=null)
line.open(af);
}
@Override
public void run(){
if(line!=null){
running=true;
int nBytesRead = 0;
try{
line.start();
while (running && nBytesRead >=0) {
nBytesRead = ais.read(buf, 0, buf.length);
if (nBytesRead >= 0) {
int nBytesWritten = line.write(buf, 0, nBytesRead);
}
Thread.yield();
}
if(running)
line.drain();
else
line.stop();
} catch(Exception ex){
System.err.println("JavaSound playing error:\n"+ex);
}
line.close();
}
ais=null;
playThread=null;
if(running && loopCount!=0){
if(loopCount>0)
loopCount--;
try{
int lc=loopCount;
FalseClip.this.start();
loopCount=lc;
} catch(Exception ex){
System.err.println("Error looping sound: "+ex);
}
}
running=false;
}
}
}