java JLayer - 暂停和恢复歌曲
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12057214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JLayer - Pause and resume song
提问by Josh M
I've noticed that a lot of topics were about pausing/resuming an MP3 using JLayer
, so in order to help everybody, I've made a whole entire class designed just for that! Please see the answer below.
我注意到很多主题都是关于使用 暂停/恢复 MP3 JLayer
,所以为了帮助大家,我制作了一个专门为此设计的整个课程!请看下面的答案。
Note: This was for my personal use, so it may not be as robust as some people were hoping. But it is not that hard to make simple modifications, due to its simplicity.
注意:这是我个人使用的,所以它可能不像某些人希望的那样健壮。但由于其简单性,进行简单的修改并不难。
回答by Durandal
A very simple implementation of a player that is really pausing playback. It works by using a separate thread to play the stream and telling the player thread if/when to pause and resume.
真正暂停播放的播放器的一个非常简单的实现。它的工作原理是使用一个单独的线程来播放流并告诉播放器线程是否/何时暂停和恢复。
public class PausablePlayer {
private final static int NOTSTARTED = 0;
private final static int PLAYING = 1;
private final static int PAUSED = 2;
private final static int FINISHED = 3;
// the player actually doing all the work
private final Player player;
// locking object used to communicate with player thread
private final Object playerLock = new Object();
// status variable what player thread is doing/supposed to do
private int playerStatus = NOTSTARTED;
public PausablePlayer(final InputStream inputStream) throws JavaLayerException {
this.player = new Player(inputStream);
}
public PausablePlayer(final InputStream inputStream, final AudioDevice audioDevice) throws JavaLayerException {
this.player = new Player(inputStream, audioDevice);
}
/**
* Starts playback (resumes if paused)
*/
public void play() throws JavaLayerException {
synchronized (playerLock) {
switch (playerStatus) {
case NOTSTARTED:
final Runnable r = new Runnable() {
public void run() {
playInternal();
}
};
final Thread t = new Thread(r);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
playerStatus = PLAYING;
t.start();
break;
case PAUSED:
resume();
break;
default:
break;
}
}
}
/**
* Pauses playback. Returns true if new state is PAUSED.
*/
public boolean pause() {
synchronized (playerLock) {
if (playerStatus == PLAYING) {
playerStatus = PAUSED;
}
return playerStatus == PAUSED;
}
}
/**
* Resumes playback. Returns true if the new state is PLAYING.
*/
public boolean resume() {
synchronized (playerLock) {
if (playerStatus == PAUSED) {
playerStatus = PLAYING;
playerLock.notifyAll();
}
return playerStatus == PLAYING;
}
}
/**
* Stops playback. If not playing, does nothing
*/
public void stop() {
synchronized (playerLock) {
playerStatus = FINISHED;
playerLock.notifyAll();
}
}
private void playInternal() {
while (playerStatus != FINISHED) {
try {
if (!player.play(1)) {
break;
}
} catch (final JavaLayerException e) {
break;
}
// check if paused or terminated
synchronized (playerLock) {
while (playerStatus == PAUSED) {
try {
playerLock.wait();
} catch (final InterruptedException e) {
// terminate player
break;
}
}
}
}
close();
}
/**
* Closes the player, regardless of current state.
*/
public void close() {
synchronized (playerLock) {
playerStatus = FINISHED;
}
try {
player.close();
} catch (final Exception e) {
// ignore, we are terminating anyway
}
}
// demo how to use
public static void main(String[] argv) {
try {
FileInputStream input = new FileInputStream("myfile.mp3");
PausablePlayer player = new PausablePlayer(input);
// start playing
player.play();
// after 5 secs, pause
Thread.sleep(5000);
player.pause();
// after 5 secs, resume
Thread.sleep(5000);
player.resume();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
回答by Josh M
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import javax.swing.JOptionPane;
import javazoom.jl.player.Player;
public class CustomPlayer {
private Player player;
private FileInputStream FIS;
private BufferedInputStream BIS;
private boolean canResume;
private String path;
private int total;
private int stopped;
private boolean valid;
public CustomPlayer(){
player = null;
FIS = null;
valid = false;
BIS = null;
path = null;
total = 0;
stopped = 0;
canResume = false;
}
public boolean canResume(){
return canResume;
}
public void setPath(String path){
this.path = path;
}
public void pause(){
try{
stopped = FIS.available();
player.close();
FIS = null;
BIS = null;
player = null;
if(valid) canResume = true;
}catch(Exception e){
}
}
public void resume(){
if(!canResume) return;
if(play(total-stopped)) canResume = false;
}
public boolean play(int pos){
valid = true;
canResume = false;
try{
FIS = new FileInputStream(path);
total = FIS.available();
if(pos > -1) FIS.skip(pos);
BIS = new BufferedInputStream(FIS);
player = new Player(BIS);
new Thread(
new Runnable(){
public void run(){
try{
player.play();
}catch(Exception e){
JOptionPane.showMessageDialog(null, "Error playing mp3 file");
valid = false;
}
}
}
).start();
}catch(Exception e){
JOptionPane.showMessageDialog(null, "Error playing mp3 file");
valid = false;
}
return valid;
}
}
And for the usage:
以及用法:
CustomPlayer player = new CustomPlayer();
player.setPath("MP3_FILE_PATH");
player.play(-1);
and then when you want to pause it:
然后当你想暂停它时:
player.pause();
...and to resume it:
...并恢复它:
player.resume();
I hope I've helped a lot of people with this.
我希望我已经帮助了很多人。
回答by Zahlii
though this question is some years old now, you should notice that this solution won't work with the newest JLayer version and the AdvancedPlayer!
尽管这个问题已经有些年头了,但您应该注意到此解决方案不适用于最新的 JLayer 版本和AdvancedPlayer!
AdvancedPlayer -> public boolean play(int frames) -> the conditional
AdvancedPlayer -> public boolean play(int frames) -> 条件
if(!ret) { .. }
has to be reintroduced, because otherwise the playback will stop after one frame played.
必须重新引入,否则播放将在播放一帧后停止。
EDIT:
编辑:
it seems that since Java 7, they handling of the daemonThreads prevents the resume from working. just remove the
似乎从 Java 7 开始,他们对 daemonThreads 的处理阻止了简历的工作。只需删除
t.setDaemon(true);
for it to work again!
让它再次工作!