Hello! I have a problem thats been stumping me for a while. I'm quite new at developing Java and I may be in over my head with this one. Please forgive me if I haven't posted in the correct format of something.
I am running Ubuntu 12.04 with 'lightweight x11 desktop environment' off of a BeagleBone Black. The Java code below is supposed to play a .wav file (Ive also tried switching to .mp3 with no luck) when a notification occurs. This all works fine on OSX but Errors out on the BeagleBone.
This is my troubleshooting so far:
I have successfully gotten the BeagleBone to make white noise through the terminal command
speaker-test -D default:CARD=Headset
I could NOT play anything using the following terminal command:
mplayer -ao alsa:device=default=Headset XXX.mp3
Also, I could not play anything using the built in audio player including the supplied .mp3. This may be irrelevant but I have also successfully commented out relevant java lines to avoid making any sound just so the program can run.
Heres the code:
package com.XXXXXX.ibis.notification;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import javax.sound.sampled.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AudioNotification implements INotification {
/**
*
* @param audioURL
* @param intervalMS
*/
public AudioNotification(URL audioURL, int intervalMS) {
m_intervalMS = intervalMS;
m_audioURL = audioURL;
}
/**
*
* @param filename
* @param intervalMS
*/
public AudioNotification(String filename, int intervalMS) {
m_intervalMS = intervalMS;
try {
m_audioURL = new URI(filename).toURL();
} catch (URISyntaxException ex) {
LOG.error("Unable to convert filename(" + filename + ") to URI", ex);
} catch (MalformedURLException ex) {
LOG.error("Unable to convert filename(" + filename + ") to URL", ex);
}
}
//**************************************************************************
//** INotification interface ***********************************************
//**************************************************************************
/**
*
* @param bActivate
*/
@Override
public void activate(boolean bActivate) {
if (bActivate != isActive()) {
if (isActive()) {
stop();
} else {
try {
start();
} catch (InterruptedException ex) {
java.util.logging.Logger.getLogger(AudioNotification.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
} // activate
/**
*
* @return
*/
@Override
public boolean isActive() {
return (m_playTask != null);
} // isActive
/**
*
*/
@Override
public void signal() {
LOG.debug("signal()");
} // signal
//**************************************************************************
//** PRIVATE METHODS *******************************************************
//**************************************************************************
/**
*
*/
private void start() throws InterruptedException {
LOG.debug("start()");
// start audio playback timer
if (m_playTask == null) {
try {
// TODO: only play 5 times?
m_playTask = new PlayClipTask(m_audioURL.openStream());
long timerIntervalMS = (m_intervalMS + m_playTask.clipLengthMS());
//m_timer.schedule(m_playTask, timerIntervalMS, timerIntervalMS);
for (int i = 0; i < REPEAT; i++) {
m_timer.schedule(m_playTask, timerIntervalMS);
Thread.sleep(timerIntervalMS * SLEEP_TIME);
m_playTask = new PlayClipTask(m_audioURL.openStream());
}
} catch (IOException ex) {
LOG.warn("start(): Error creating play task", ex);
}
} else {
LOG.warn("start(): Playback already in progress");
}
} // start
/**
*
*/
private void stop() {
LOG.debug("stop()");
// cancel audio playback timer
if (m_playTask != null) {
m_playTask.stopPlayback();
m_playTask.cancel();
m_playTask = null;
}
} // stop
//**************************************************************************
//** PRIVATE CLASSES *******************************************************
//**************************************************************************
private class PlayClipTask extends TimerTask {
/**
*
* @param source
*/
public PlayClipTask(InputStream source) {
m_clip = loadAudioClip(source);
}
/**
*
* @return
*/
public long clipLengthMS() {
if (m_clip != null) {
return (m_clip.getMicrosecondLength() / 1000L);
} else {
return (0);
}
} // clipLengthMS
/**
*
*/
@Override
public void run() {
if (m_clip != null) {
if (m_clip.isActive()) {
LOG.debug("PlayClipTask.run(): stop audio clip");
m_clip.stop(); // reset
}
m_clip.setFramePosition(0);
LOG.debug("PlayClipTask.run(): start audio clip");
m_clip.start();
} else {
LOG.warn("PlayClipTask.run(): Clip is NULL");
}
} // run
/**
*
*/
public void stopPlayback() {
if (m_clip != null) {
LOG.debug("PlayClipTask.stopPlayback(): stop audio clip");
if (m_clip.isActive()) {
m_clip.stop();
}
m_clip.flush();
m_clip.close();
m_clip = null;
} else {
LOG.warn("PlayClipTask.stopPlayback(): Clip is NULL");
}
} // stopPlayback
/**
*
* @param source
* @return
*/
private Clip loadAudioClip(InputStream source) {
Clip theClip = null;
try {
// read audio from source
// add buffer for mark/reset support
InputStream bufferedSource = new BufferedInputStream(source);
AudioInputStream inStream = AudioSystem.getAudioInputStream(bufferedSource);
AudioFormat f = inStream.getFormat();
theClip = (Clip)AudioSystem.getLine(new DataLine.Info(Clip.class, f));
theClip.open(inStream);
} catch (UnsupportedAudioFileException ex) {
LOG.error("PlayClipTask.loadAudioFile()", ex);
} catch (LineUnavailableException ex) {
LOG.error("PlayClipTask.loadAudioFile()", ex);
} catch (IOException ex) {
LOG.error("PlayClipTask.loadAudioFile()", ex);
}
return (theClip);
} // loadAudioClip
private Clip m_clip = null;
} // class PlayClipTask
//**************************************************************************
//** PRIVATE VARIABLES *****************************************************
//**************************************************************************
private static final Logger LOG = LoggerFactory.getLogger(AudioNotification.class);
// private static final String DEFAULT_SOUND = "com/XXXXXXX/YYYYY/audio/Minke_Whale.wav";
private final int m_intervalMS;
private URL m_audioURL = null;
private Timer m_timer = new Timer();
private PlayClipTask m_playTask = null;
private final static int REPEAT = 4; // HAS
private final static int SLEEP_TIME = 1; // HAS
} // class AudioNotification
and the error is:
ERROR AudioNotification - PlayClipTask.loadAudioFile()
javax.sound.sampled.LineUnavailableException: null
Could the BeagleBone Black be incapable of playing audio files using Java? Or is there a change I can implement in the code to work around the error? Any help is appreciated!