使用jlayer

时间:2016-02-02 15:20:10

标签: java streaming jgroups jlayer

我正在研究Java中的mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),并且客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器以块的形式发送文件,并以块的形式接收文件并播放它。我正在使用jgroups库进行组成员资格管理,因为我计划扩展许多客户端使用的应用程序。这是我到目前为止所尝试的:

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");
    }
}

根据我当前的实现,播放器只播放一帧,但我希望它能够播放收到的整个mp3文件。我在这做错了什么?如何同步服务器和客户端,以便客户端在收到文件后立即播放整个流?欢迎任何建议。

0 个答案:

没有答案