1363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/* 2363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Copyright (C) 2010 The Android Open Source Project 3363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 4363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * you may not use this file except in compliance with the License. 6363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * You may obtain a copy of the License at 7363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 8363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 9363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 10363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Unless required by applicable law or agreed to in writing, software 11363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 12363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * See the License for the specific language governing permissions and 14363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * limitations under the License. 15363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 16363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 17363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpackage android.net.rtp; 18363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 19363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.InetAddress; 20363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.SocketException; 21363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 22363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/** 2332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * An AudioStream is a {@link RtpStream} which carrys audio payloads over 2432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Real-time Transport Protocol (RTP). Two different classes are developed in 2532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * order to support various usages such as audio conferencing. An AudioStream 2632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * represents a remote endpoint which consists of a network mapping and a 2732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * configured {@link AudioCodec}. On the other side, An {@link AudioGroup} 2832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * represents a local endpoint which mixes all the AudioStreams and optionally 2932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * interacts with the speaker and the microphone at the same time. The simplest 30c52f5b2ec5e13ab3d9ab016e6cab757d4ecb45c7Chia-chi Yeh * usage includes one for each endpoints. For other combinations, developers 31c52f5b2ec5e13ab3d9ab016e6cab757d4ecb45c7Chia-chi Yeh * should be aware of the limitations described in {@link AudioGroup}. 3232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * 3332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most 3432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * of the setter methods are disabled. This is designed to ease the task of 3532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * managing native resources. One can always make an AudioStream leave its 3632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it 3753aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * back after the modification is done.</p> 3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * 3953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * <p class="note">Using this class requires 4053aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p> 4153aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * 4253aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * @see RtpStream 4332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @see AudioGroup 44363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 45363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class AudioStream extends RtpStream { 46363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private AudioCodec mCodec; 47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private int mDtmfType = -1; 48363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private AudioGroup mGroup; 49363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 50363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 51363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Creates an AudioStream on the given local address. Note that the local 52363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * port is assigned automatically to conform with RFC 3550. 53363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 54363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param address The network address of the local host to bind to. 55363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SocketException if the address cannot be bound or a problem 56363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * occurs during binding. 57363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 58363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public AudioStream(InetAddress address) throws SocketException { 59363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang super(address); 60363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 61363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 6332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Returns {@code true} if the stream has already joined an 6432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * {@link AudioGroup}. 65363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 67363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public final boolean isBusy() { 68363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mGroup != null; 69363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 70363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 71363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 72363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the joined {@link AudioGroup}. 73363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 7432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh public AudioGroup getGroup() { 75363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mGroup; 76363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 77363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 78363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 79363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Joins an {@link AudioGroup}. Each stream can join only one group at a 80363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * time. The group can be changed by passing a different one or removed 81363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * by calling this method with {@code null}. 82363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 83363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param group The AudioGroup to join or {@code null} to leave. 84363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is not properly configured. 85363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see AudioGroup 86363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 87363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void join(AudioGroup group) { 8853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh synchronized (this) { 8953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh if (mGroup == group) { 9053aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh return; 9153aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh } 9253aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh if (mGroup != null) { 9353aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh mGroup.remove(this); 9453aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh mGroup = null; 9553aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh } 9653aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh if (group != null) { 97e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh group.add(this); 9853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh mGroup = group; 9953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh } 100363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 101363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 102363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 103363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 10437adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * Returns the {@link AudioCodec}, or {@code null} if it is not set. 10537adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * 10637adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * @see #setCodec(AudioCodec) 10737adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh */ 10837adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh public AudioCodec getCodec() { 10937adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh return mCodec; 11037adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh } 11137adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh 11237adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh /** 11332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Sets the {@link AudioCodec}. 114363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 115363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param codec The AudioCodec to be used. 11632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @throws IllegalArgumentException if its type is used by DTMF. 117363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 11932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh public void setCodec(AudioCodec codec) { 120363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 122363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 12332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh if (codec.type == mDtmfType) { 124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("The type is used by DTMF"); 125363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mCodec = codec; 127363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 128363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 13037adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits, 13137adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * or {@code -1} if it is not enabled. 13237adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * 13337adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * @see #setDtmfType(int) 13437adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh */ 13537adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh public int getDtmfType() { 13637adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh return mDtmfType; 13737adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh } 13837adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh 13937adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh /** 140363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits. 141363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * The primary usage is to send digits to the remote gateway to perform 142363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * certain tasks, such as second-stage dialing. According to RFC 2833, the 143363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * RTP payload type for DTMF is assigned dynamically, so it must be in the 144363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * range of 96 and 127. One can use {@code -1} to disable DTMF and free up 14537adc522f6bc074a688ffbef420a8627ef9a4b5bChia-chi Yeh * the previous assigned type. This method cannot be called when the stream 146363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * already joined an {@link AudioGroup}. 147363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 148363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param type The RTP payload type to be used or {@code -1} to disable it. 149363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalArgumentException if the type is invalid or used by codec. 150363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 151363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see AudioGroup#sendDtmf(int) 152363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 153363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void setDtmfType(int type) { 154363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 155363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 156363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 157363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (type != -1) { 158363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (type < 96 || type > 127) { 159363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("Invalid type"); 160363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 161fb982db41060a2914cddb43200f3ee53627f8762Chia-chi Yeh if (mCodec != null && type == mCodec.type) { 162363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("The type is used by codec"); 163363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 164363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 165363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mDtmfType = type; 166363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 167363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang} 168