La class VisualPlayer regroupe les fonctionnalités suivantes:
1. interface graphique pour piloter le Thread de lecture,
2. ajout des fonctions pause et stop,
3. affichage de la progression de lecture.
Au travers de cet exemple, la communication entre un Thread et une interface graphique est abordée. Au lieu du Timer, un Thread 'écouteur' aurait été une variante pour le rafraichissement de la JProgressBar
Thread de lecture d'un avi
Les nouvelles fonctions permettent de mieux piloter le Thread de lecture du fichier wav:- pause(): mettre en pause ou reprendre la lecture,
- cancel(): abandonner la lecture,
- getProgress(): connaitre la progression de lecture.
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Player de sons wav
* ajout de fonctions à la class AePlayWave
* http://www.fobec.com/java/1043/jouer-son-musique-format-wav.html
* -> pause et reprendre la lecture
* -> arreter la lecture
* -> calculer la progression de lecture.
* @author fobec 2011 *
*/
public class WavePlayerThread extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 65536; // 16Kb
private boolean isSuspend = false;
private boolean isCanceled = false;
private VisualPlayer frame = null;
private int readpercent = 0;
enum Position {
LEFT, RIGHT, NORMAL
};
/**
* Constructeur: fixer le fichier wav
* @param wavfile
*/
public WavePlayerThread(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
/**
* Mettre en pause ou reprendre la lecture
*/
public synchronized void pause() {
if (this.isSuspend == true) {
this.isSuspend = false;
} else {
this.isSuspend = true;
}
notify();
}
/**
* Abandonner la lecture
*/
public synchronized void cancel() {
this.isCanceled = true;
notify();
}
/**
* Fixer la Frame VisualPlayer
* @param visualplayer
*/
public void setFrame(VisualPlayer visualplayer) {
this.frame = visualplayer;
}
/**
* Connaitre la progression de lecture
* @return
*/
public int getProgress() {
return this.readpercent;
}
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT) {
pan.setValue(1.0f);
} else if (curPosition == Position.LEFT) {
pan.setValue(-1.0f);
}
}
auline.start();
int nBytesRead = 0;
//longueur du fichier wav
Long audiolength = soundFile.length();
int audioreaded = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1 && this.isCanceled == false) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0) {
//calcul de la progression
readpercent = Math.round(audioreaded * 100 / audiolength);
auline.write(abData, 0, nBytesRead);
audioreaded = nBytesRead;
}
/**
* Annuler la lecture
*/
if (this.isCanceled == true) {
System.out.print("Thread has been stopped");
break;
}
/**
* Mettre en pause
*/
if (this.isSuspend == true) {
while (this.isSuspend == true) {
try {
Thread.sleep(250);
if (this.isCanceled == true) {
System.out.print("Thread has been stopped");
break;
}
} catch (InterruptedException ex) {
Logger.getLogger(WavePlayerThread.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
/**
* Fin du thread de lecture
*/
readpercent = 100;
this.frame.onTerminated();
}
}
Interface graphique VisualPlayer
Interface minimaliste pour suivre et piloter la lecture d'un wav, à savoir 3 boutons et 1 barre de progression.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
/**
* Interface grpahique de lecture d'un son wav
* @author fobec 2011
*/
public class VisualPlayer extends JFrame {
private WavePlayerThread thread = null;
private JProgressBar jprogressbar = null;
private JButton jButton_pause = null;
private String wavefile = "";
private Timer timer = null;
/**
* Constructor
* @param filename
*/
public VisualPlayer(String filename) {
this.wavefile = filename;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 75);
setLocation(200, 200);
setTitle("Lecture de " filename);
/**
* Composant graphique
*/
JPanel buttonpanel = new JPanel();
buttonpanel.setLayout(new GridLayout(2, 2, 2, 2));
JButton jButton_play = new javax.swing.JButton();
jButton_play.setText("Play");
jButton_play.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
play();
}
});
jButton_pause = new javax.swing.JButton();
jButton_pause.setText("Pause");
jButton_pause.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
pause();
}
});
JButton jButton_stop = new javax.swing.JButton();
jButton_stop.setText("Stop");
jButton_stop.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
stop();
}
});
buttonpanel.add(jButton_play);
buttonpanel.add(jButton_pause);
buttonpanel.add(jButton_stop);
getContentPane().add(buttonpanel);
jprogressbar = new JProgressBar();
jprogressbar.setStringPainted(true);
buttonpanel.add(jprogressbar);
/**
* Timer de suivi de la progression
*/
this.timer = new Timer(250,
new ActionListener() {
public void actionPerformed(ActionEvent event) {
updateUI();
}
});
setVisible(true);
}
/**
* Lancer la lecture
*/
public void play() {
if (this.thread == null) {
this.thread = new WavePlayerThread(this.wavefile);
this.thread.setFrame(this);
this.thread.start();
this.timer.start();
}
}
/**
* Mettre en pause ou reprendre la lecture
*/
public void pause() {
if (this.thread != null) {
if (jButton_pause.getText().equalsIgnoreCase("Pause")) {
jButton_pause.setText("Reprendre");
} else {
jButton_pause.setText("Pause");
}
this.thread.pause();
}
}
/**
* Abandonner la lecture
*/
public void stop() {
if (this.thread != null) {
this.thread.cancel();
//will call onTerminated
}
}
/**
* Timer event: mettre à jour la progressbar
*/
public void updateUI() {
if (this.thread != null) {
jprogressbar.setValue(this.thread.getProgress());
}
}
/**
* Thread event: fin du thread de lecture
*/
public void onTerminated() {
System.out.print("end");
updateUI();
this.timer.stop();
this.thread = null;
// pour relancer la lecture
// play();
}
/**
* Exemple de lancement de la class
* @param args
*/
public static void main(String[] args) {
VisualPlayer player = new VisualPlayer("C:tambour.wav");
player.setVisible(true);
}
}