/* * 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}. * *

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.

* *

Using this class requires * {@link android.Manifest.permission#INTERNET} permission.

* * @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); 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 (mCodec != null && type == mCodec.type) { throw new IllegalArgumentException("The type is used by codec"); } } mDtmfType = type; } }