package com.hubPlayer.player; import java.io.File; import java.io.IOException; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.Timer; import java.util.TimerTask; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.DataLine.Info; import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.JOptionPane; import org.jaudiotagger.audio.AudioFile; import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.AudioHeader; import org.jaudiotagger.audio.exceptions.CannotReadException; import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; import org.jaudiotagger.tag.TagException; import com.hubPlayer.ui.tool.TimeProgressBar; /** * 底层播放器,主要控制播放 * * @date 2014-10-18 */ public class BasicPlayer { public SourceDataLine sourceDataLine; private AudioInputStream audioInputStream; public URL audio; public boolean HTTPFlag; public Thread playThread; public boolean IsPause = true;// 是否停止播放状态 public boolean NeedContinue;// 当播放同一首歌曲 是否继续播放状态 public boolean IsComplete; public boolean IsEnd; // 检测输入流是否阻塞 private boolean IsChoke; private Timer checkConnection; // 音量控制 private FloatControl floatVoiceControl; public TimeProgressBar timerProgressBar; public synchronized void play() { try { // 获取网络音频输入流 if (HTTPFlag) { try { HttpURLConnection urlConnection = (HttpURLConnection) audio .openConnection(); audioInputStream = AudioSystem .getAudioInputStream(urlConnection.getInputStream()); // 用计时器监测歌曲连接状态 初始启动计时器 checkConnectionSchedule(); } catch (ConnectException e) { // 进度条清零 timerProgressBar.cleanTimer(); // 连接超时 JOptionPane.showMessageDialog(null, "网络资源连接异常", "", JOptionPane.PLAIN_MESSAGE); return; } } // else // 获取本地音频输入流 audioInputStream = AudioSystem.getAudioInputStream(audio); // 获取音频编码格式 AudioFormat audioFormat = audioInputStream.getFormat(); // MPEG1L3转PCM_SIGNED if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) { audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, audioFormat.getSampleRate(), 16, audioFormat.getChannels(), audioFormat.getChannels() * 2, audioFormat.getSampleRate(), false); audioInputStream = AudioSystem.getAudioInputStream(audioFormat, audioInputStream); } // 根据上面的音频格式获取输出设备信息 DataLine.Info info = new Info(SourceDataLine.class, audioFormat); // 获取输出设备对象 sourceDataLine = (SourceDataLine) AudioSystem.getLine(info); // 打开输出管道 sourceDataLine.open(); // 允许此管道执行数据 I/O sourceDataLine.start(); // 获取总音量的控件 floatVoiceControl = (FloatControl) sourceDataLine .getControl(FloatControl.Type.MASTER_GAIN); // 音量minValue -80 maxValue 6 // 设合适的初始音量 floatVoiceControl.setValue(-20); byte[] buf = new byte[1024]; int onceReadDataSize = 0; while ((onceReadDataSize = audioInputStream .read(buf, 0, buf.length)) != -1) { // 输入流没有阻塞 IsChoke = false; if (IsEnd) { return; } // 是否暂停 if (IsPause) pause(); // 将数据写入混频器中 至输出端口写完前阻塞 sourceDataLine.write(buf, 0, onceReadDataSize); // 预设输入流阻塞 IsChoke = true; } IsChoke = false; // 冲刷缓冲区数据 sourceDataLine.drain(); sourceDataLine.close(); audioInputStream.close(); if (checkConnection != null) { checkConnection.cancel(); checkConnection.purge(); checkConnection = null; // System.out.println("EndTimeOutControl"); } } catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException e) { e.printStackTrace(); } } public void load(URL url) { this.audio = url; } public void checkConnectionSchedule() { checkConnection = new Timer(true); checkConnection.schedule(new TimerTask() { // 阻塞计数 int times = 0; @Override public void run() { if (IsChoke) { times++; // 如果检测到阻塞次数有20次 if (times == 20) { try { // 进度条清零 timerProgressBar.cleanTimer(); // 使playThread自然执行完 IsEnd = false; // 输入流关闭 audioInputStream.close(); JOptionPane.showMessageDialog(null, "连接异常中断", "", JOptionPane.PLAIN_MESSAGE); } catch (Exception e) { e.printStackTrace(); } } } else times = 0; // System.out.println(times); } }, 2000, 500); } public synchronized void resume() { IsPause = false; NeedContinue = false; this.notify(); } private synchronized void pause() throws InterruptedException { NeedContinue = true; this.wait(); } public void end() { try { if (playThread == null) return; IsPause = true; NeedContinue = false; IsComplete = false; IsEnd = true; // 关闭当前数据输入管道 sourceDataLine.close(); audioInputStream.close(); playThread = null; } catch (Exception e) { System.out.println("中断播放当前歌曲"); IsPause = true; NeedContinue = false; IsComplete = false; IsEnd = true; } } // 获取音频文件的长度 秒数 public int getAudioTrackLength(URL url) { try { // 只能获得本地歌曲文件的信息 AudioFile file = AudioFileIO.read(new File(url.toURI())); // 获取音频文件的头信息 AudioHeader audioHeader = file.getAudioHeader(); // 文件长度 转换成时间 return audioHeader.getTrackLength(); } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException | URISyntaxException e) { e.printStackTrace(); return -1; } } public String getAudioTotalTime(int sec) { String time = "0:00"; if (sec <= 0) return time; int minute = sec / 60; int second = sec % 60; int hour = minute / 60; if (second < 10) time = minute + ":0" + second; else time = minute + ":" + second; if (hour != 0) time = hour + ":" + time; return time; } public SourceDataLine getSourceDataLine() { return sourceDataLine; } public FloatControl getFloatControl() { return floatVoiceControl; } }