Package com.pugh.sockso.music.stream

Source Code of com.pugh.sockso.music.stream.RangeStream$Range

package com.pugh.sockso.music.stream;

import com.pugh.sockso.Utils;
import com.pugh.sockso.music.Track;
import com.pugh.sockso.web.Response;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import org.apache.log4j.Logger;

/**
* For client requested streaming from arbitrary starting point
*
* @author Nathan Perrier
*/
public class RangeStream extends AbstractMusicStream {

    private static final Logger log = Logger.getLogger(RangeStream.class);

    private Range range;

    public RangeStream( final Track track, final Range range ) {
        super(track);
        this.range = range;
    }

    @Override
    public void setHeaders( final Response response ) {
        super.setHeaders(response);
       
        final long trackLength = new File(this.track.getPath()).length();

        // set headers required to satisfy Range requests:
        // Content-Length: 2980
        final long contentLength = range.getLength();
        // Content-Range: bytes 1000-3979/3980
        final String contentRange = "bytes " + range.getStart() + "-" + range.getEnd() + "/" + trackLength;

        response.setStatus(206); // Partial Content
        response.addHeader("Content-Range", contentRange);
        response.addHeader("Content-Length", Long.toString(contentLength));
        response.addHeader("Accept-Ranges", "bytes");

    }

    /**
     * Sends the music stream to the client, optionally handling range
     * requests
     *
     * @throws java.io.IOException
     *
     */
    public void sendAudioStream( final DataOutputStream client ) throws IOException {

        DataInputStream audio = getAudioStream();

        long contentLength = this.range.getLength();

        byte[] buffer = new byte[STREAM_BUFFER_SIZE];
        int readBlock = STREAM_BUFFER_SIZE;
        long totalBytes = 0;
       
        try {

            audio.skip(this.range.start);
            log.debug("Skipped " + this.range.start + " bytes");

            int nextRead = -1;
            for ( int bytesRead = 0; bytesRead >= 0 && totalBytes < contentLength; bytesRead = audio.read(buffer, 0, readBlock) ) {

                totalBytes += bytesRead;

                if ( totalBytes + readBlock > contentLength ) {
                    readBlock = (int) (contentLength - totalBytes);
                }

                client.write(buffer, 0, bytesRead);

                if ( totalBytes > nextRead ) {
                    nextRead += STREAM_BUFFER_SIZE * 12; // print ~every 100 KB
                    log.debug(String.format("Sent %2d%%", bytesRead));
                }

            }

        } finally {
            Utils.close(audio);
            Utils.close(client);
        }

    }

   
    /**
     * Simple pair of values with the constraint that start &lt; end
     */
    public static class Range {

        private long start;
        private long end;

        public Range( long start, long end ) {
            assert start >= 0;
            assert end > 0;
            assert start < end;

            this.start = start;
            this.end = end;
        }

        public long getStart() {
            return this.start;
        }

        public long getEnd() {
            return this.end;
        }

        // start and end represent byte positions, so we need to +1
        public long getLength() {
            return end - start + 1;
        }
    }

}
TOP

Related Classes of com.pugh.sockso.music.stream.RangeStream$Range

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.