Java JLayer-暂停并继续播放歌曲
我注意到很多主题都是关于使用Java JLayer-暂停并继续播放歌曲,java,playback,resume,jlayer,Java,Playback,Resume,Jlayer,我注意到很多主题都是关于使用JLayer暂停/恢复MP3的,所以为了帮助大家,我专门设计了一整节课!请看下面的答案 注意:这是我个人使用的,所以它可能不像一些人希望的那样坚固。但由于其简单性,进行简单的修改并不难 import java.io.BufferedInputStream; import java.io.FileInputStream; import javax.swing.JOptionPane; import javazoom.jl.player.Player; publi
JLayer
暂停/恢复MP3的,所以为了帮助大家,我专门设计了一整节课!请看下面的答案
注意:这是我个人使用的,所以它可能不像一些人希望的那样坚固。但由于其简单性,进行简单的修改并不难
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;
}
}
至于用途:
CustomPlayer player = new CustomPlayer();
player.setPath("MP3_FILE_PATH");
player.play(-1);
然后,当您想暂停时:
player.pause();
…并继续:
player.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);
}
}
}
虽然这个问题已经有几年历史了,但是您应该注意到,这个解决方案不适用于最新的JLayer版本和AdvancedPlayer AdvancedPlayer->公共布尔播放(int帧)->条件
if(!ret) { .. }
必须重新引入,否则播放将在播放一帧后停止
编辑:
似乎从Java7开始,对daemonThreads的处理就阻止了恢复工作。只需移除
t.setDaemon(true);
让它再次工作 即使你只是为了分享你的代码而创建了一个问题,这个问题也应该看起来像一个问题。第一句话解释了。在我看来,你应该像真正的问题一样排列你的问题文本(带问号和stuff=)。不需要解释。当前的问题文本更适合回答。嗯,我想我可以这样做。但考虑到我只是对人们一直在问的问题做了一个笔记,与这个话题类似,我认为没有必要这么做。如果你说很多人对此有问题,那就意味着有太多的问题。你为什么不把你的代码放在这些问题的答案中呢?你不是暂停玩家,而是杀死它,然后创建一个新的。此外,它不会从停止的位置继续,而是在以后的任意字节数(取决于停止时BufferedInputStream的满度)。“恢复”时,您将流定位在某个位置,而不是有效的帧头(jlayer通常会处理这个问题,除非流数据中出现0xFFFx,否则它将崩溃)。依赖FileInputStream.available()来获取文件的长度也是非常值得怀疑的。。。如果您想播放文件以外的内容,则不是很灵活;这是一个解决办法。我认为这是最简单的方法,而且我知道.available()方法返回流中剩余字节数的估计值,当我测试它时,它从暂停时的不到半秒处恢复。显然,当您测试它时,您一定得到了不同的结果。只要您意识到您的解决方案的局限性,就可以了。在大多数情况下,它应该完成工作。我之所以发表评论,是因为您可能希望改进我提到的问题(请不要将其视为个人问题)。“目标”精度取决于为BufferedInputStream和streams比特率选择的缓冲区大小。如果代码用户决定使用更大的缓冲区(比如256kb),它将跳过几秒钟。你可以通过计算BufferedInputStream中可能耗尽的字节数来解决这个问题,当然这会增加代码的复杂性。我知道,我也很欣赏你的批评,但我觉得这是获得非常好的结果的最简单的方法。当我看到其他类似问题的答案时,没有一个显示任何代码,他们的过程似乎太复杂和困难了,大多数人都不明白这意味着什么。只要看一下我的解决方案中的代码,它就非常简单,没有一个部分是任何人都不应该理解的。嗨,很好的帖子,我有一个问题:当参数为-1时,你用FIS.skip(pos)做什么?如果我在参数中输入0或50?谢谢!