I’m pretty stumped here. I wrote a very basic program to test an MP3 abstraction we’ve been working on in a separate Eclipse project. The MP3 class has 3 dependencies which I moved over to the main project, and we copied the class as well. However, when trying to play a song on the new project, suddenly the code stopped working. The fix? Remove the SWT jar. I can’t figure out why it works, but removing SWT makes the MP3 play, and adding it back in breaks it again. The only thing contained in swt.jar is org.eclipse.swt code, as confirmed by decompiling with JD-GUI. The catch is that none of the audio code imports anything from org.eclipse.swt. Any idea how adding the SWT files in can completely break the MP3 code?
My test file:
MP3 mp3 = new MP3(new File("four-chord-song.mp3"));
mp3.play(60);
Scanner in = new Scanner(System.in);
long lastTime = System.currentTimeMillis();
while (true) {
in.nextLine();
System.out.println(System.currentTimeMillis() - lastTime);
lastTime = System.currentTimeMillis();
}
And the MP3 file (kinda messy, the line that hangs with SWT is noted):
package com.partyrock.music;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.*;
public class MP3 extends Sound {
private File file;
private boolean isPaused;
private boolean isPlaying;
private AudioFileFormat fileFormat;
private Thread MP3Thread;
private SourceDataLine line;
private AudioInputStream din;
private MP3Player myMP3Player;
private double startTime = 0;
/**
* Constructs an MP3 from a given file.
* @param file The file
*/
public MP3(File file) {
super();
this.file = file;
isPaused = false;
if (!file.exists()) {
System.err.println("MP3 constructed for non-existent file");
return;
}
try {
fileFormat = AudioSystem.getAudioFileFormat(file);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class MP3Player implements Runnable {
private double startTime;
boolean paused;
public MP3Player(double var) {
this.startTime = var;
paused = false;
}
public void run() {
din = null;
try {
AudioInputStream in = AudioSystem.getAudioInputStream(file);
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
// ****** This is the line that breaks when SWT is included
line = (SourceDataLine) javax.sound.sampled.AudioSystem.getLine(info);
if (line != null) {
line.open(decodedFormat);
byte[] data = new byte[4096];
// Start
line.start();
isPlaying = true;
// Skip first startTime seconds
int bytesToSkip = (int) (startTime
* (Integer) fileFormat.properties().get("mp3.bitrate.nominal.bps") / 8);
din.skip(bytesToSkip);
int nBytesRead;
while ((data != null) && (din != null) && (nBytesRead = din.read(data, 0, data.length)) != -1
&& isPlaying) {
// Skip first startTime seconds
if (isPaused == true) {
while (isPaused) {
Thread.sleep(100);
}
}
line.write(data, 0, nBytesRead);
// System.out.println(line.getMicrosecondPosition());
}
isPlaying = false;
// Stop
if (line != null && din != null) {
line.drain();
line.stop();
line.close();
din.close();
}
}
} catch (Exception e) {
System.out.println("Error!");
e.printStackTrace();
} finally {
if (din != null) {
try {
din.close();
} catch (IOException e) {
}
}
}
}
}
@Override
public void play(double startTime) {
this.startTime = startTime;
myMP3Player = new MP3Player(startTime);
MP3Thread = new Thread(myMP3Player);
MP3Thread.start();
}
public void playthread(double startTime) {
}
@Override
public double getDuration() {
// TODO Auto-generated method stub
Long microseconds = (Long) fileFormat.properties().get("duration");
double milliseconds = (int) (microseconds / 1000);
double seconds = (milliseconds / 1000);
return seconds;
}
@Override
public void pause() {
// TODO Auto-generated method stub
isPaused = true;
// MP3Thread.suspend();
myMP3Player.paused = true;
}
public void unpause() {
// TODO Auto-generated method stub
isPaused = false;
myMP3Player.paused = false;
// MP3Thread.resume();
}
@Override
public double getCurrentTime() {
// TODO Auto-generated method stub
System.out.println(line.getMicrosecondPosition());
return startTime + (line.getMicrosecondPosition() / 1000);
}
/**
* Returns the file associated with this MP3
* @return The mp3 file
*/
public File getFile() {
return file;
}
public void stop() {
isPlaying = false;
pause();
MP3Thread = null;
myMP3Player = null;
isPaused = false;
isPlaying = false;
// fileFormat = null;
MP3Thread = null;
line = null;
din = null;
myMP3Player = null;
startTime = 0;
// Stop
// line.drain();
// line.stop();
// line.close();
}
}
I’m quite confused as to how, but I re-downloaded the latest SWT, and it worked, although I had to add the
-XstartOnFirstThreadargument when launching or I got the***WARNING: Display must be created on main thread due to Cocoa restrictions.error.