Java 使用jlayer重复播放流式mp3数据

Java 使用jlayer重复播放流式mp3数据,java,streaming,jgroups,jlayer,Java,Streaming,Jgroups,Jlayer,我正在用Java开发一个mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器分块发送文件,也分块接收并播放文件。我正在使用库进行组成员管理,因为我计划扩展应用程序以供许多客户使用。以下是我迄今为止所尝试的: import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.player.Player; import or

我正在用Java开发一个mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器分块发送文件,也分块接收并播放文件。我正在使用库进行组成员管理,因为我计划扩展应用程序以供许多客户使用。以下是我迄今为止所尝试的:

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
import org.apache.commons.io.input.CountingInputStream;
import org.jgroups.*;
import org.jgroups.conf.ClassConfigurator;
import org.jgroups.util.Util;

import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Xabush on 1/25/2016 21:43.
 * Project: DSP_Java
 */
public class SimpleMPlayer extends ReceiverAdapter {

    private CountingInputStream in;
    private Player player;
    private String filename;
    protected File file;
    protected int offest = 0;
    protected JChannel channel;
    protected int frames;
    protected boolean isServer = true;
    protected Map<String, OutputStream> files = new ConcurrentHashMap<String, OutputStream>();
    protected static final short ID = 3500;

    public SimpleMPlayer(String filename) throws IOException, JavaLayerException {
        this.filename = filename;
        file = new File(this.filename);
        in = new CountingInputStream(new FileInputStream(filename));
        player = new Player(new FileInputStream("src/np/test.mp3"));
    }

    public void start(String name) throws Exception {
        ClassConfigurator.add((short) 3500, FileHeader.class);
        channel = new JChannel("src/jgroups/fast.xml").name(name);
        channel.setReceiver(this);
        channel.connect("File_Cluster");
        if (isServer)
            eventLoop();
    }

    private void eventLoop() throws Exception {
        Util.keyPress(String.format("<enter to send %s>\n", file.getName()));
        sendFile();

        System.out.print("Finished sending file");

    }

    protected void sendFile() throws Exception {
        try {
            int read = 0;
            while (read != -1) {
                byte[] buff = new byte[2304];
                read = in.read(buff);
                offest += in.getByteCount();
                frames += 1;
                sendMessage(buff, 0, buff.length, false, frames);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sendMessage(null, 0, 0, true, frames);
        }
    }

    protected void sendMessage(byte[] buf, int offset, int length, boolean eof, int fr) throws Exception {
        Message msg = new Message(null, buf, offset, length).putHeader(ID, new FileHeader(filename, eof, fr));
        // set this if the sender doesn't want to receive the file
        msg.setTransientFlag(Message.TransientFlag.DONT_LOOPBACK);
        channel.send(msg);
    }

    public void receive(Message msg) {
        byte[] buf = msg.getRawBuffer();
        FileHeader hdr = (FileHeader) msg.getHeader(ID);
        if (hdr == null)
            return;
        OutputStream out = files.get(hdr.filename);
        int frame = hdr.frame;
        try {
            if (out == null) {
                File tmp = new File(hdr.filename);
                String fname = tmp.getName();
                fname = "src/np/" + fname;
                out = new FileOutputStream(fname);
                files.put(hdr.filename, out);

            }
            if (hdr.eof) {
                Util.close(files.remove(hdr.filename));
            } else {
                out.write(msg.getRawBuffer(), msg.getOffset(), msg.getLength());
                playFromStream(frame);
            }

        } catch (Throwable t) {
            System.err.println(t);
        }
    }

    public void playFromStream(int fr) throws IOException {
        try {
            player.play(fr);
        } catch (JavaLayerException e) {
            player.close();
            e.printStackTrace();
        }

    }

    public boolean isServer() {
        return isServer;
    }

    public void setServer(boolean server) {
        isServer = server;
    }

    protected static class FileHeader extends Header {
        protected String filename;
        protected boolean eof;
        protected int frame;

        public FileHeader() {
        } // for de-serialization

        public FileHeader(String filename, boolean eof, int fr) {
            this.filename = filename;
            this.eof = eof;
            this.frame = fr;
        }

        public int size() {
            return Util.size(filename) + Global.BYTE_SIZE;
        }

        public void writeTo(DataOutput out) throws Exception {
            Util.writeObject(filename, out);
            out.writeBoolean(eof);
            out.writeInt(frame);
        }

        public void readFrom(DataInput in) throws Exception {
            filename = (String) Util.readObject(in);
            eof = in.readBoolean();
            frame = in.readInt();
        }
    }

    public static void main(String[] args) throws Exception {
        SimpleMPlayer mplayer = new SimpleMPlayer("src/jgroups/test.mp3"); // name and file

        if (args[0].equalsIgnoreCase("server")) {
            mplayer.setServer(true);
        } else {
            mplayer.setServer(false);
        }
        mplayer.start("MusicChannel");
    }
}
导入javazoom.jl.decoder.JavaLayerException;
导入javazoom.jl.player.player;
导入org.apache.commons.io.input.CountingInputStream;
导入org.jgroups.*;
导入org.jgroups.conf.ClassConfigurator;
导入org.jgroups.util.util;
导入java.io.*;
导入java.util.Map;
导入java.util.concurrent.ConcurrentHashMap;
/**
*由Xabush于2016年1月25日21:43创建。
*项目:DSP_Java
*/
公共类SimplePlayer扩展了ReceiverAdapter{
私有计数输入流;
私人玩家;
私有字符串文件名;
受保护的文件;
受保护的int offest=0;
保护JChannel信道;
受保护的int帧;
受保护的布尔值isServer=true;
受保护的映射文件=新的ConcurrentHashMap();
受保护静态最终短路ID=3500;
公共SimplePlayer(字符串文件名)抛出IOException、JavaLayerException{
this.filename=文件名;
file=新文件(此.filename);
in=新计数输入流(新文件输入流(文件名));
player=新播放器(新文件输入流(“src/np/test.mp3”);
}
public void start(字符串名称)引发异常{
添加((短)3500,FileHeader.class);
channel=newjchannel(“src/jgroups/fast.xml”).name(name);
信道设置接收器(本);
channel.connect(“文件集群”);
如果(isServer)
eventLoop();
}
私有void eventLoop()引发异常{
Util.keyPress(String.format(“\n”,file.getName());
sendFile();
系统输出打印(“已完成发送文件”);
}
受保护的void sendFile()引发异常{
试一试{
int read=0;
while(读取!=-1){
字节[]buff=新字节[2304];
read=in.read(buff);
offest+=in.getByteCount();
帧+=1;
sendMessage(buff,0,buff.length,false,frames);
}
}捕获(例外e){
e、 printStackTrace();
}最后{
sendMessage(null、0、0、true、帧);
}
}
受保护的void sendMessage(字节[]buf,整数偏移量,整数长度,布尔eof,整数fr)引发异常{
Message msg=新消息(null、buf、偏移量、长度).putHeader(ID、新文件头(文件名、eof、fr));
//如果发件人不想接收文件,请设置此选项
msg.setTransientFlag(Message.TransientFlag.DONT_环回);
频道发送(msg);
}
公共无效接收(消息消息消息){
字节[]buf=msg.getRawBuffer();
FileHeader hdr=(FileHeader)msg.getHeader(ID);
如果(hdr==null)
返回;
OutputStream out=files.get(hdr.filename);
int frame=hdr.frame;
试一试{
if(out==null){
文件tmp=新文件(hdr.filename);
字符串fname=tmp.getName();
fname=“src/np/”+fname;
out=新文件输出流(fname);
files.put(hdr.filename,out);
}
如果(hdr.eof){
Util.close(files.remove(hdr.filename));
}否则{
write(msg.getRawBuffer(),msg.getOffset(),msg.getLength());
playFromStream(帧);
}
}捕获(可丢弃的t){
系统错误println(t);
}
}
公共void playFromStream(int-fr)引发IOException{
试一试{
player.play(fr);
}捕获(JavaLayerXe){
player.close();
e、 printStackTrace();
}
}
公共布尔值isServer(){
返回isServer;
}
公共void设置服务器(布尔服务器){
isServer=服务器;
}
受保护的静态类FileHeader扩展标头{
受保护的字符串文件名;
保护布尔eof;
受保护的int帧;
公共文件头(){
}//用于反序列化
公共文件头(字符串文件名、布尔eof、整数fr){
this.filename=文件名;
this.eof=eof;
this.frame=fr;
}
公共整数大小(){
返回Util.size(文件名)+Global.BYTE\u size;
}
public void writeTo(DataOutput out)引发异常{
Util.writeObject(文件名,out);
out.writebolean(eof);
out.writeInt(帧);
}
public void readFrom(DataInput in)引发异常{
filename=(字符串)Util.readObject(in);
eof=in.readBoolean();
frame=in.readInt();
}
}
公共静态void main(字符串[]args)引发异常{
SimpleMPlayer-mplayer=newsimplemplayer(“src/jgroups/test.mp3”);//名称和文件
if(参数[0].equalsIgnoreCase(“服务器”)){
mplayer.setServer(true);
}否则{
mplayer.setServer(false);
}
mplayer.start(“音乐频道”);
}
}
在我当前的实现中,播放器只播放一帧,但我希望它在接收时播放整个mp3文件。我做错了什么?如何同步服务器和客户端,以便客户端在收到文件后立即播放整个流?欢迎提出任何建议