一个迷你音乐播放器

1. 写在前面

写一个MP3播放器,支持播放和暂停。

2. PausablePlayer

PausablePlayer集成开源项目JLayer,支持音乐暂停与播放。

<dependency>
    <groupId>javazoom</groupId>
    <artifactId>jlayer</artifactId>
    <version>1.0.1</version>
</dependency>

发现该资源的网址:http://www.voidcn.com/article/p-cucatrfz-buo.html

具体代码如下:(对源代码稍作修改)

package com.music.player;

import java.io.InputStream;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.Player;

/**
 * from http://www.voidcn.com/article/p-cucatrfz-buo.html
 *
 */
public class PausablePlayer {

    public final static int NOTSTARTED = 0;
    public final static int PLAYING = 1;
    public final static int PAUSED = 2;
    public 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
        }
    }

    public int getPlayerStatus() {
        return playerStatus;
    }

    public void setPlayerStatus(int playerStatus) {
        this.playerStatus = playerStatus;
    }

}

3. 制作图形界面

直接使用Swing制作。

package com.music.player;

import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class PlayerFrame extends JFrame {

    private static final long serialVersionUID = 9066225937591877119L;
    private JButton btnBrowse, playBtn, pauseBtn;
    private JTextField textPath;

    public PlayerFrame() {
        setTitle("音乐播放器");
        setLayout(new GridLayout(4, 1));
        Container container = getContentPane();
        btnBrowse = new JButton("打开文件");
        container.add(btnBrowse);

        textPath = new JTextField();
        container.add(textPath);

        playBtn = new JButton("播放");
        container.add(playBtn);

        pauseBtn = new JButton("暂停");
        container.add(pauseBtn);

        setVisible(true);
        setSize(400, 250);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public JButton getBtnBrowse() {
        return btnBrowse;
    }

    public JButton getPlayBtn() {
        return playBtn;
    }

    public JButton getPauseBtn() {
        return pauseBtn;
    }

    public JTextField getTextPath() {
        return textPath;
    }
}

4. 成品

给图形界面的按钮添加事件,完成作品。

package com.music.player;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import javax.swing.JFileChooser;
import javax.swing.JTextField;

import javazoom.jl.decoder.JavaLayerException;

/**
 * 音乐播放示例:Swing + JLayler
 *
 */
public class App {
    // 声明一个全局变量,方便匿名内部类中使用
    public static PausablePlayer pausablePlayer = null;
    static File openFile = null;
    static JTextField textPath = null;

    public static void clear() {
        if (pausablePlayer != null) {
            pausablePlayer.close();
            pausablePlayer = null;
        }
    }

    public static void main(String[] args) {
        create();
    }

    public static void create() {
        PlayerFrame playerFrame = new PlayerFrame();
        textPath = playerFrame.getTextPath();
        // 打开文件按钮添加事件
        playerFrame.getBtnBrowse().addActionListener(e -> {

            JFileChooser chooser = new JFileChooser(); // 文件选择
            chooser.showOpenDialog(chooser); // 打开文件选择窗
            openFile = chooser.getSelectedFile(); // 获取选择的文件

            // 如果未选择文件,不继续执行
            if (openFile == null)
                return;

            clear(); // 停止上一次选择的音乐

            textPath.setText(openFile.getPath()); // 获取选择文件的路径

            initPlayer(); // 初始化播放器
        });
        // 播放按钮添加事件
        playerFrame.getPlayBtn().addActionListener(e -> {
            if (pausablePlayer == null) {
                textPath.setText("请选择一首音乐!");
                return;
            }
            // 如果音乐已播放完,再点击播放可重新开始播放
            if (PausablePlayer.FINISHED == pausablePlayer.getPlayerStatus()) {
                initPlayer();
            }
            try {
                pausablePlayer.play();
            } catch (JavaLayerException e1) {
                e1.printStackTrace();
            }
        });
        // 暂停按钮添加事件
        playerFrame.getPauseBtn().addActionListener(e -> {
            if (pausablePlayer == null) {
                textPath.setText("请选择一首音乐!");
                return;
            }
            pausablePlayer.pause();
        });
    }

    public static void initPlayer() {
        FileInputStream input = null;
        try {
            input = new FileInputStream(openFile);
        } catch (FileNotFoundException e2) {
            e2.printStackTrace();
        }
        try {
            pausablePlayer = new PausablePlayer(input);
        } catch (JavaLayerException e1) {
            e1.printStackTrace();
        }
    }
}

文章作者: 叶遮沉阳
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 叶遮沉阳 !
  目录