diff --git a/peers-demo/src/main/java/net/sourceforge/peers/demo/CustomConfig.java b/peers-demo/src/main/java/net/sourceforge/peers/demo/CustomConfig.java
index 9883f0f8..8a1c31ea 100644
--- a/peers-demo/src/main/java/net/sourceforge/peers/demo/CustomConfig.java
+++ b/peers-demo/src/main/java/net/sourceforge/peers/demo/CustomConfig.java
@@ -60,5 +60,9 @@ public void setPublicInetAddress(InetAddress inetAddress) {
@Override public void setRtpPort(int rtpPort) { }
@Override public void save() { }
@Override public void setAuthorizationUsername(String authorizationUsername) { }
-
+
+ public long getRtpSendInterval() {
+ return 0;
+ }
+
}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/Config.java b/peers-lib/src/main/java/net/sourceforge/peers/Config.java
index 3249f3d3..7697381f 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/Config.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/Config.java
@@ -51,5 +51,5 @@ public interface Config {
public void setMediaFile(String mediaFile);
public void setRtpPort(int rtpPort);
public void setAuthorizationUsername(String authorizationUsername);
-
+ public long getRtpSendInterval();
}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/JavaConfig.java b/peers-lib/src/main/java/net/sourceforge/peers/JavaConfig.java
index a21f438c..7e9d1787 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/JavaConfig.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/JavaConfig.java
@@ -152,6 +152,10 @@ public void setAuthorizationUsername(String authorizationUsername) {
this.authorizationUsername = authorizationUsername;
}
+ public long getRtpSendInterval() {
+ return 19562000;
+ }
+
@Override
public String getMediaFile() {
return mediaFile;
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/XmlConfig.java b/peers-lib/src/main/java/net/sourceforge/peers/XmlConfig.java
index 6e3e60aa..2a5923bb 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/XmlConfig.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/XmlConfig.java
@@ -52,12 +52,8 @@ public class XmlConfig implements Config {
public final static int RTP_DEFAULT_PORT = 8000;
private Logger logger;
-
private File file;
private Document document;
-
- // persistent variables
-
private InetAddress localInetAddress;
private String userPart;
private String domain;
@@ -365,6 +361,10 @@ public void setAuthorizationUsername(String authorizationUsername) {
authUserNode.setTextContent(authorizationUsername);
}
+ public long getRtpSendInterval() {
+ return 0;
+ }
+
@Override
public String getMediaFile() {
return mediaFile;
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java b/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
index 0c54cb54..c90f6173 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
@@ -274,7 +274,7 @@ public void sendDtmf(char digit) {
public void stopSession() {
if (rtpSession != null) {
rtpSession.stop();
- while (!rtpSession.isSocketClosed()) {
+ while (rtpSession !=null && !rtpSession.isSocketClosed()) {
try {
Thread.sleep(15);
} catch (InterruptedException e) {
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/media/RtpSender.java b/peers-lib/src/main/java/net/sourceforge/peers/media/RtpSender.java
index 093ec30f..d73c377b 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/media/RtpSender.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/media/RtpSender.java
@@ -100,8 +100,7 @@ public void run() {
long offset = 0;
long lastSentTime = System.nanoTime();
// indicate if its the first time that we send a packet (dont wait)
- boolean firstTime = true;
-
+ int firstTimes = 0;
while (!isStopped) {
numBytesRead = 0;
try {
@@ -150,12 +149,13 @@ public void run() {
timestamp += buf_size;
}
rtpPacket.setTimestamp(timestamp);
- if (firstTime) {
+ if (firstTimes < 15) {
rtpSession.send(rtpPacket);
lastSentTime = System.nanoTime();
- firstTime = false;
+ firstTimes++;
continue;
}
+ // todo改成config里取
sleepTime = 19500000 - (System.nanoTime() - lastSentTime) + offset;
if (sleepTime > 0) {
try {
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/rtp/RtpSession.java b/peers-lib/src/main/java/net/sourceforge/peers/rtp/RtpSession.java
index ee258849..1cb3308c 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/rtp/RtpSession.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/rtp/RtpSession.java
@@ -174,18 +174,9 @@ public Void run() {
}
class Receiver implements Runnable {
-
+ private final byte[] buf = new byte[512];
@Override
public void run() {
- int receiveBufferSize;
- try {
- receiveBufferSize = datagramSocket.getReceiveBufferSize();
- } catch (SocketException e) {
- logger.error("cannot get datagram socket receive buffer size",
- e);
- return;
- }
- byte[] buf = new byte[receiveBufferSize];
final DatagramPacket datagramPacket = new DatagramPacket(buf,
buf.length);
final int noException = 0;
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/SipListener.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/SipListener.java
index de9c5adc..7e480338 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/SipListener.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/SipListener.java
@@ -25,20 +25,20 @@
public interface SipListener {
- public void registering(SipRequest sipRequest);
+ void registering(SipRequest sipRequest);
- public void registerSuccessful(SipResponse sipResponse);
+ void registerSuccessful(SipResponse sipResponse);
- public void registerFailed(SipResponse sipResponse);
+ void registerFailed(SipResponse sipResponse);
- public void incomingCall(SipRequest sipRequest, SipResponse provResponse);
+ void incomingCall(SipRequest sipRequest, SipResponse provResponse);
- public void remoteHangup(SipRequest sipRequest);
+ void remoteHangup(SipRequest sipRequest);
- public void ringing(SipResponse sipResponse);
+ void ringing(SipResponse sipResponse);
- public void calleePickup(SipResponse sipResponse);
+ void calleePickup(SipResponse sipResponse);
- public void error(SipResponse sipResponse);
+ void error(SipResponse sipResponse);
}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/ServerTransactionUser.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/ServerTransactionUser.java
index b17e7080..cfab6b35 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/ServerTransactionUser.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/ServerTransactionUser.java
@@ -21,5 +21,5 @@
public interface ServerTransactionUser {
- public void transactionFailure();
+ void transactionFailure();
}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedInputStream.java b/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedInputStream.java
new file mode 100644
index 00000000..3c2d8a6e
--- /dev/null
+++ b/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedInputStream.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+package net.sourceforge.peers.stream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A piped input stream should be connected
+ * to a piped output stream; the piped input
+ * stream then provides whatever data bytes
+ * are written to the piped output stream.
+ * Typically, data is read from a PipedInputStream
+ * object by one thread and data is written
+ * to the corresponding MediaPipedOutputStream
+ * by some other thread. Attempting to use
+ * both objects from a single thread is not
+ * recommended, as it may deadlock the thread.
+ * The piped input stream contains a buffer,
+ * decoupling read operations from write operations,
+ * within limits.
+ * A pipe is said to be broken if a
+ * thread that was providing data bytes to the connected
+ * piped output stream is no longer alive.
+ *
+ * @author James Gosling
+ * @see java.io.PipedOutputStream
+ * @since JDK1.0
+ */
+public class MediaPipedInputStream extends InputStream {
+
+
+ boolean closedByWriter = false;
+ volatile boolean closedByReader = false;
+ boolean connected = false;
+
+ /* REMIND: identification of the read and write sides needs to be
+ more sophisticated. Either using thread groups (but what about
+ pipes within a thread?) or using finalization (but it may be a
+ long time until the next GC). */
+ Thread readSide;
+ Thread writeSide;
+
+ private static final int DEFAULT_PIPE_SIZE = 1024;
+
+ /**
+ * The default size of the pipe's circular input buffer.
+ * @since JDK1.1
+ */
+ // This used to be a constant before the pipe size was allowed
+ // to change. This field will continue to be maintained
+ // for backward compatibility.
+ protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;
+
+ /**
+ * The circular buffer into which incoming data is placed.
+ * @since JDK1.1
+ */
+ protected byte buffer[];
+
+ /**
+ * The index of the position in the circular buffer at which the
+ * next byte of data will be stored when received from the connected
+ * piped output stream. in<0
implies the buffer is empty,
+ * in==out
implies the buffer is full
+ * @since JDK1.1
+ */
+ protected int in = -1;
+
+ /**
+ * The index of the position in the circular buffer at which the next
+ * byte of data will be read by this piped input stream.
+ * @since JDK1.1
+ */
+ protected int out = 0;
+
+ /**
+ * Creates a PipedInputStream
so
+ * that it is connected to the piped output
+ * stream src
. Data bytes written
+ * to src
will then be available
+ * as input from this stream.
+ *
+ * @param src the stream to connect to.
+ * @exception IOException if an I/O error occurs.
+ */
+ public MediaPipedInputStream(MediaPipedOutputStream src) throws IOException {
+ this(src, DEFAULT_PIPE_SIZE);
+ }
+
+ /**
+ * Creates a PipedInputStream
so that it is
+ * connected to the piped output stream
+ * src
and uses the specified pipe size for
+ * the pipe's buffer.
+ * Data bytes written to src
will then
+ * be available as input from this stream.
+ *
+ * @param src the stream to connect to.
+ * @param pipeSize the size of the pipe's buffer.
+ * @exception IOException if an I/O error occurs.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
+ * @since 1.6
+ */
+ public MediaPipedInputStream(MediaPipedOutputStream src, int pipeSize)
+ throws IOException {
+ initPipe(pipeSize);
+ connect(src);
+ }
+
+ /**
+ * Creates a PipedInputStream
so
+ * that it is not yet {@linkplain #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream)
+ * connected}.
+ * It must be {@linkplain java.io.PipedOutputStream#connect(
+ * java.io.PipedInputStream) connected} to a
+ * PipedOutputStream
before being used.
+ */
+ public MediaPipedInputStream() {
+ initPipe(DEFAULT_PIPE_SIZE);
+ }
+
+ /**
+ * Creates a PipedInputStream
so that it is not yet
+ * {@linkplain #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) connected} and
+ * uses the specified pipe size for the pipe's buffer.
+ * It must be {@linkplain java.io.PipedOutputStream#connect(
+ * java.io.PipedInputStream)
+ * connected} to a PipedOutputStream
before being used.
+ *
+ * @param pipeSize the size of the pipe's buffer.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
+ * @since 1.6
+ */
+ public MediaPipedInputStream(int pipeSize) {
+ initPipe(pipeSize);
+ }
+
+ private void initPipe(int pipeSize) {
+ if (pipeSize <= 0) {
+ throw new IllegalArgumentException("Pipe Size <= 0");
+ }
+ buffer = new byte[pipeSize];
+ }
+
+ /**
+ * Causes this piped input stream to be connected
+ * to the piped output stream src
.
+ * If this object is already connected to some
+ * other piped output stream, an IOException
+ * is thrown.
+ *
+ * If src
is an
+ * unconnected piped output stream and snk
+ * is an unconnected piped input stream, they
+ * may be connected by either the call:
+ *
+ *
snk.connect(src)
+ * + * or the call: + * + *
src.connect(snk)
+ *
+ * The two calls have the same effect.
+ *
+ * @param src The piped output stream to connect to.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void connect(MediaPipedOutputStream src) throws IOException {
+ src.connect(this);
+ }
+
+ /**
+ * Receives a byte of data. This method will block if no input is
+ * available.
+ * @param b the byte being received
+ * @exception IOException If the pipe is broken
,
+ * {@link #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) unconnected},
+ * closed, or if an I/O error occurs.
+ * @since JDK1.1
+ */
+ protected synchronized void receive(int b) throws IOException {
+ checkStateForReceive();
+ writeSide = Thread.currentThread();
+ if (in == out)
+ awaitSpace();
+ if (in < 0) {
+ in = 0;
+ out = 0;
+ }
+ buffer[in++] = (byte)(b & 0xFF);
+ if (in >= buffer.length) {
+ in = 0;
+ }
+ }
+
+ /**
+ * Receives data into an array of bytes. This method will
+ * block until some input is available.
+ * @param b the buffer into which the data is received
+ * @param off the start offset of the data
+ * @param len the maximum number of bytes received
+ * @exception IOException If the pipe is broken,
+ * {@link #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) unconnected},
+ * closed,or if an I/O error occurs.
+ */
+ synchronized void receive(byte b[], int off, int len) throws IOException {
+ checkStateForReceive();
+ writeSide = Thread.currentThread();
+ int bytesToTransfer = len;
+ while (bytesToTransfer > 0) {
+ if (in == out)
+ awaitSpace();
+ int nextTransferAmount = 0;
+ if (out < in) {
+ nextTransferAmount = buffer.length - in;
+ } else if (in < out) {
+ if (in == -1) {
+ in = out = 0;
+ nextTransferAmount = buffer.length - in;
+ } else {
+ nextTransferAmount = out - in;
+ }
+ }
+ if (nextTransferAmount > bytesToTransfer)
+ nextTransferAmount = bytesToTransfer;
+ assert(nextTransferAmount > 0);
+ System.arraycopy(b, off, buffer, in, nextTransferAmount);
+ bytesToTransfer -= nextTransferAmount;
+ off += nextTransferAmount;
+ in += nextTransferAmount;
+ if (in >= buffer.length) {
+ in = 0;
+ }
+ }
+ }
+
+ private void checkStateForReceive() throws IOException {
+ if (!connected) {
+ throw new IOException("Pipe not connected");
+ } else if (closedByWriter || closedByReader) {
+ throw new IOException("Pipe closed");
+ } else if (readSide != null && !readSide.isAlive()) {
+ throw new IOException("Read end dead");
+ }
+ }
+
+ private void awaitSpace() throws IOException {
+ while (in == out) {
+ checkStateForReceive();
+
+ /* full: kick any waiting readers */
+ notifyAll();
+ try {
+ // 语音播放,不太适合等待1s
+ wait(20);
+ } catch (InterruptedException ex) {
+ throw new java.io.InterruptedIOException();
+ }
+ }
+ }
+
+ /**
+ * Notifies all waiting threads that the last byte of data has been
+ * received.
+ */
+ synchronized void receivedLast() {
+ closedByWriter = true;
+ notifyAll();
+ }
+
+ /**
+ * Reads the next byte of data from this piped input stream. The
+ * value byte is returned as an int
in the range
+ * 0
to 255
.
+ * This method blocks until input data is available, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next byte of data, or -1
if the end of the
+ * stream is reached.
+ * @exception IOException if the pipe is
+ * {@link #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) unconnected},
+ * broken
, closed,
+ * or if an I/O error occurs.
+ */
+ public synchronized int read() throws IOException {
+ if (!connected) {
+ throw new IOException("Pipe not connected");
+ } else if (closedByReader) {
+ throw new IOException("Pipe closed");
+ } else if (writeSide != null && !writeSide.isAlive()
+ && !closedByWriter && (in < 0)) {
+ throw new IOException("Write end dead");
+ }
+
+ readSide = Thread.currentThread();
+ int trials = 2;
+ while (in < 0) {
+ if (closedByWriter) {
+ /* closed by writer, return EOF */
+ return -1;
+ }
+ if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
+ throw new IOException("Pipe broken");
+ }
+ /* might be a writer waiting */
+ notifyAll();
+ try {
+ // 语音播放,不太适合等待1s
+ wait(20);
+ } catch (InterruptedException ex) {
+ throw new java.io.InterruptedIOException();
+ }
+ }
+ int ret = buffer[out++] & 0xFF;
+ if (out >= buffer.length) {
+ out = 0;
+ }
+ if (in == out) {
+ /* now empty */
+ in = -1;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Reads up to len
bytes of data from this piped input
+ * stream into an array of bytes. Less than len
bytes
+ * will be read if the end of the data stream is reached or if
+ * len
exceeds the pipe's buffer size.
+ * If len
is zero, then no bytes are read and 0 is returned;
+ * otherwise, the method blocks until at least 1 byte of input is
+ * available, end of the stream has been detected, or an exception is
+ * thrown.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1
if there is no more data because the end of
+ * the stream has been reached.
+ * @exception NullPointerException If b
is null
.
+ * @exception IndexOutOfBoundsException If off
is negative,
+ * len
is negative, or len
is greater than
+ * b.length - off
+ * @exception IOException if the pipe is broken
,
+ * {@link #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) unconnected},
+ * closed, or if an I/O error occurs.
+ */
+ public synchronized int read(byte b[], int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ /* possibly wait on the first character */
+ int c = read();
+ if (c < 0) {
+ return -1;
+ }
+ b[off] = (byte) c;
+ int rlen = 1;
+ while ((in >= 0) && (len > 1)) {
+
+ int available;
+
+ if (in > out) {
+ available = Math.min((buffer.length - out), (in - out));
+ } else {
+ available = buffer.length - out;
+ }
+
+ // A byte is read beforehand outside the loop
+ if (available > (len - 1)) {
+ available = len - 1;
+ }
+ System.arraycopy(buffer, out, b, off + rlen, available);
+ out += available;
+ rlen += available;
+ len -= available;
+
+ if (out >= buffer.length) {
+ out = 0;
+ }
+ if (in == out) {
+ /* now empty */
+ in = -1;
+ }
+ }
+ return rlen;
+ }
+
+ /**
+ * Returns the number of bytes that can be read from this input
+ * stream without blocking.
+ *
+ * @return the number of bytes that can be read from this input stream
+ * without blocking, or {@code 0} if this input stream has been
+ * closed by invoking its {@link #close()} method, or if the pipe
+ * is {@link #connect(cn.com.autohome.aaa.aidcc.robot.soft.phone.peers.stream.MediaPipedOutputStream) unconnected}, or
+ * broken
.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JDK1.0.2
+ */
+ public synchronized int available() throws IOException {
+ if(in < 0)
+ return 0;
+ else if(in == out)
+ return buffer.length;
+ else if (in > out)
+ return in - out;
+ else
+ return in + buffer.length - out;
+ }
+
+ /**
+ * Closes this piped input stream and releases any system resources
+ * associated with the stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ public void close() throws IOException {
+ closedByReader = true;
+ synchronized (this) {
+ in = -1;
+ }
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ this.out = 0;
+ this.in = -1;
+ this.notifyAll();
+ }
+}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedOutputStream.java b/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedOutputStream.java
new file mode 100644
index 00000000..152ea400
--- /dev/null
+++ b/peers-lib/src/main/java/net/sourceforge/peers/stream/MediaPipedOutputStream.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+package net.sourceforge.peers.stream;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A piped output stream can be connected to a piped input stream
+ * to create a communications pipe. The piped output stream is the
+ * sending end of the pipe. Typically, data is written to a
+ * PipedOutputStream
object by one thread and data is
+ * read from the connected PipedInputStream
by some
+ * other thread. Attempting to use both objects from a single thread
+ * is not recommended as it may deadlock the thread.
+ * The pipe is said to be broken if a
+ * thread that was reading data bytes from the connected piped input
+ * stream is no longer alive.
+ *
+ * @author James Gosling
+ * @see java.io.PipedInputStream
+ * @since JDK1.0
+ */
+public class MediaPipedOutputStream extends OutputStream {
+
+ /* REMIND: identification of the read and write sides needs to be
+ more sophisticated. Either using thread groups (but what about
+ pipes within a thread?) or using finalization (but it may be a
+ long time until the next GC). */
+ private MediaPipedInputStream sink;
+
+ /**
+ * Creates a piped output stream connected to the specified piped
+ * input stream. Data bytes written to this stream will then be
+ * available as input from snk
.
+ *
+ * @param snk The piped input stream to connect to.
+ * @exception IOException if an I/O error occurs.
+ */
+ public MediaPipedOutputStream(MediaPipedInputStream snk) throws IOException {
+ connect(snk);
+ }
+
+ /**
+ * Creates a piped output stream that is not yet connected to a
+ * piped input stream. It must be connected to a piped input stream,
+ * either by the receiver or the sender, before being used.
+ *
+ * @see java.io.PipedInputStream#connect(java.io.PipedOutputStream)
+ * @see java.io.PipedOutputStream#connect(java.io.PipedInputStream)
+ */
+ public MediaPipedOutputStream() {
+ }
+
+ /**
+ * Connects this piped output stream to a receiver. If this object
+ * is already connected to some other piped input stream, an
+ * IOException
is thrown.
+ *
+ * If snk
is an unconnected piped input stream and
+ * src
is an unconnected piped output stream, they may
+ * be connected by either the call:
+ *
+ * or the call: + *+ * src.connect(snk)
+ * The two calls have the same effect. + * + * @param snk the piped input stream to connect to. + * @exception IOException if an I/O error occurs. + */ + public synchronized void connect(MediaPipedInputStream snk) throws IOException { + if (snk == null) { + throw new NullPointerException(); + } else if (sink != null || snk.connected) { + throw new IOException("Already connected"); + } + sink = snk; + snk.in = -1; + snk.out = 0; + snk.connected = true; + } + + /** + * Writes the specified+ * snk.connect(src)
byte
to the piped output stream.
+ *
+ * Implements the write
method of OutputStream
.
+ *
+ * @param b the byte
to be written.
+ * @exception IOException if the pipe is broken,
+ * {@link #connect(java.io.PipedInputStream) unconnected},
+ * closed, or if an I/O error occurs.
+ */
+ public void write(int b) throws IOException {
+ if (sink == null) {
+ throw new IOException("Pipe not connected");
+ }
+ sink.receive(b);
+ }
+
+ /**
+ * Writes len
bytes from the specified byte array
+ * starting at offset off
to this piped output stream.
+ * This method blocks until all the bytes are written to the output
+ * stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if the pipe is broken,
+ * {@link #connect(java.io.PipedInputStream) unconnected},
+ * closed, or if an I/O error occurs.
+ */
+ public void write(byte b[], int off, int len) throws IOException {
+ if (sink == null) {
+ throw new IOException("Pipe not connected");
+ } else if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ sink.receive(b, off, len);
+ }
+
+ /**
+ * Flushes this output stream and forces any buffered output bytes
+ * to be written out.
+ * This will notify any readers that bytes are waiting in the pipe.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ public synchronized void flush() throws IOException {
+ if (sink != null) {
+ synchronized (sink) {
+ sink.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Closes this piped output stream and releases any system resources
+ * associated with this stream. This stream may no longer be used for
+ * writing bytes.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ public void close() throws IOException {
+ if (sink != null) {
+ sink.receivedLast();
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index a1bd43f6..d1566281 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,24 +1,39 @@
-