| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.net.rtp; |
| |
| import java.net.InetAddress; |
| import java.net.SocketException; |
| |
| /** |
| * An AudioStream is a {@link RtpStream} which carrys audio payloads over |
| * Real-time Transport Protocol (RTP). Two different classes are developed in |
| * order to support various usages such as audio conferencing. An AudioStream |
| * represents a remote endpoint which consists of a network mapping and a |
| * configured {@link AudioCodec}. On the other side, An {@link AudioGroup} |
| * represents a local endpoint which mixes all the AudioStreams and optionally |
| * interacts with the speaker and the microphone at the same time. The simplest |
| * usage includes one for each endpoints. For other combinations, developers |
| * should be aware of the limitations described in {@link AudioGroup}. |
| * |
| * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most |
| * of the setter methods are disabled. This is designed to ease the task of |
| * managing native resources. One can always make an AudioStream leave its |
| * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it |
| * back after the modification is done.</p> |
| * |
| * <p class="note">Using this class requires |
| * {@link android.Manifest.permission#INTERNET} permission.</p> |
| * |
| * @see RtpStream |
| * @see AudioGroup |
| */ |
| public class AudioStream extends RtpStream { |
| private AudioCodec mCodec; |
| private int mDtmfType = -1; |
| private AudioGroup mGroup; |
| |
| /** |
| * Creates an AudioStream on the given local address. Note that the local |
| * port is assigned automatically to conform with RFC 3550. |
| * |
| * @param address The network address of the local host to bind to. |
| * @throws SocketException if the address cannot be bound or a problem |
| * occurs during binding. |
| */ |
| public AudioStream(InetAddress address) throws SocketException { |
| super(address); |
| } |
| |
| /** |
| * Returns {@code true} if the stream has already joined an |
| * {@link AudioGroup}. |
| */ |
| @Override |
| public final boolean isBusy() { |
| return mGroup != null; |
| } |
| |
| /** |
| * Returns the joined {@link AudioGroup}. |
| */ |
| public AudioGroup getGroup() { |
| return mGroup; |
| } |
| |
| /** |
| * Joins an {@link AudioGroup}. Each stream can join only one group at a |
| * time. The group can be changed by passing a different one or removed |
| * by calling this method with {@code null}. |
| * |
| * @param group The AudioGroup to join or {@code null} to leave. |
| * @throws IllegalStateException if the stream is not properly configured. |
| * @see AudioGroup |
| */ |
| public void join(AudioGroup group) { |
| synchronized (this) { |
| if (mGroup == group) { |
| return; |
| } |
| if (mGroup != null) { |
| mGroup.remove(this); |
| mGroup = null; |
| } |
| if (group != null) { |
| group.add(this, mCodec, mDtmfType); |
| mGroup = group; |
| } |
| } |
| } |
| |
| /** |
| * Returns the {@link AudioCodec}, or {@code null} if it is not set. |
| * |
| * @see #setCodec(AudioCodec) |
| */ |
| public AudioCodec getCodec() { |
| return mCodec; |
| } |
| |
| /** |
| * Sets the {@link AudioCodec}. |
| * |
| * @param codec The AudioCodec to be used. |
| * @throws IllegalArgumentException if its type is used by DTMF. |
| * @throws IllegalStateException if the stream is busy. |
| */ |
| public void setCodec(AudioCodec codec) { |
| if (isBusy()) { |
| throw new IllegalStateException("Busy"); |
| } |
| if (codec.type == mDtmfType) { |
| throw new IllegalArgumentException("The type is used by DTMF"); |
| } |
| mCodec = codec; |
| } |
| |
| /** |
| * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits, |
| * or {@code -1} if it is not enabled. |
| * |
| * @see #setDtmfType(int) |
| */ |
| public int getDtmfType() { |
| return mDtmfType; |
| } |
| |
| /** |
| * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits. |
| * The primary usage is to send digits to the remote gateway to perform |
| * certain tasks, such as second-stage dialing. According to RFC 2833, the |
| * RTP payload type for DTMF is assigned dynamically, so it must be in the |
| * range of 96 and 127. One can use {@code -1} to disable DTMF and free up |
| * the previous assigned type. This method cannot be called when the stream |
| * already joined an {@link AudioGroup}. |
| * |
| * @param type The RTP payload type to be used or {@code -1} to disable it. |
| * @throws IllegalArgumentException if the type is invalid or used by codec. |
| * @throws IllegalStateException if the stream is busy. |
| * @see AudioGroup#sendDtmf(int) |
| */ |
| public void setDtmfType(int type) { |
| if (isBusy()) { |
| throw new IllegalStateException("Busy"); |
| } |
| if (type != -1) { |
| if (type < 96 || type > 127) { |
| throw new IllegalArgumentException("Invalid type"); |
| } |
| if (type == mCodec.type) { |
| throw new IllegalArgumentException("The type is used by codec"); |
| } |
| } |
| mDtmfType = type; |
| } |
| } |