198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/* 298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Copyright (C) 2010 The Android Open Source Project 398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * you may not use this file except in compliance with the License. 698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * You may obtain a copy of the License at 798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 1098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Unless required by applicable law or agreed to in writing, software 1198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 1298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * See the License for the specific language governing permissions and 1498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * limitations under the License. 1598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 1698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpackage android.net.rtp; 1898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.InetAddress; 2098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.SocketException; 2198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 2298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/** 237f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * An AudioStream is a {@link RtpStream} which carrys audio payloads over 247f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Real-time Transport Protocol (RTP). Two different classes are developed in 257f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * order to support various usages such as audio conferencing. An AudioStream 267f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * represents a remote endpoint which consists of a network mapping and a 277f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * configured {@link AudioCodec}. On the other side, An {@link AudioGroup} 287f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * represents a local endpoint which mixes all the AudioStreams and optionally 297f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * interacts with the speaker and the microphone at the same time. The simplest 300a3e1f1851b26657b865ae3c91200c59dfc411feChia-chi Yeh * usage includes one for each endpoints. For other combinations, developers 310a3e1f1851b26657b865ae3c91200c59dfc411feChia-chi Yeh * should be aware of the limitations described in {@link AudioGroup}. 327f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * 337f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most 347f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * of the setter methods are disabled. This is designed to ease the task of 357f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * managing native resources. One can always make an AudioStream leave its 367f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it 37a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * back after the modification is done.</p> 387f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * 39a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * <p class="note">Using this class requires 40a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p> 41a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * 42a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * @see RtpStream 437f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * @see AudioGroup 4498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 4598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class AudioStream extends RtpStream { 4698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private AudioCodec mCodec; 4798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private int mDtmfType = -1; 4898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private AudioGroup mGroup; 4998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 5098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 5198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Creates an AudioStream on the given local address. Note that the local 5298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * port is assigned automatically to conform with RFC 3550. 5398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 5498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param address The network address of the local host to bind to. 5598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SocketException if the address cannot be bound or a problem 5698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * occurs during binding. 5798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 5898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public AudioStream(InetAddress address) throws SocketException { 5998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang super(address); 6098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 6198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 6298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 637f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Returns {@code true} if the stream has already joined an 647f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * {@link AudioGroup}. 6598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 6698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 6798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public final boolean isBusy() { 6898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mGroup != null; 6998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 7098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 7198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 7298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Returns the joined {@link AudioGroup}. 7398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 747f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh public AudioGroup getGroup() { 7598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mGroup; 7698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 7798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 7898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 7998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Joins an {@link AudioGroup}. Each stream can join only one group at a 8098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * time. The group can be changed by passing a different one or removed 8198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * by calling this method with {@code null}. 8298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 8398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param group The AudioGroup to join or {@code null} to leave. 8498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is not properly configured. 8598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @see AudioGroup 8698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 8798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void join(AudioGroup group) { 88a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh synchronized (this) { 89a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh if (mGroup == group) { 90a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh return; 91a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh } 92a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh if (mGroup != null) { 93a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh mGroup.remove(this); 94a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh mGroup = null; 95a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh } 96a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh if (group != null) { 972bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh group.add(this); 98a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh mGroup = group; 99a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh } 10098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 10198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 10298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 10398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 10407c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * Returns the {@link AudioCodec}, or {@code null} if it is not set. 10507c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * 10607c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * @see #setCodec(AudioCodec) 10707c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh */ 10807c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh public AudioCodec getCodec() { 10907c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh return mCodec; 11007c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh } 11107c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh 11207c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh /** 1137f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Sets the {@link AudioCodec}. 11498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 11598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param codec The AudioCodec to be used. 1167f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * @throws IllegalArgumentException if its type is used by DTMF. 11798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is busy. 11898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 1197f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh public void setCodec(AudioCodec codec) { 12098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (isBusy()) { 12198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalStateException("Busy"); 12298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 1237f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh if (codec.type == mDtmfType) { 12498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("The type is used by DTMF"); 12598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 12698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mCodec = codec; 12798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 12898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 12998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 13007c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits, 13107c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * or {@code -1} if it is not enabled. 13207c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * 13307c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * @see #setDtmfType(int) 13407c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh */ 13507c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh public int getDtmfType() { 13607c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh return mDtmfType; 13707c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh } 13807c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh 13907c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh /** 14098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits. 14198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * The primary usage is to send digits to the remote gateway to perform 14298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * certain tasks, such as second-stage dialing. According to RFC 2833, the 14398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * RTP payload type for DTMF is assigned dynamically, so it must be in the 14498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * range of 96 and 127. One can use {@code -1} to disable DTMF and free up 14507c7dc5e0b1465a83fbe33d3b94f7ebceccbdee0Chia-chi Yeh * the previous assigned type. This method cannot be called when the stream 14698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * already joined an {@link AudioGroup}. 14798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 14898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param type The RTP payload type to be used or {@code -1} to disable it. 14998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalArgumentException if the type is invalid or used by codec. 15098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is busy. 15198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @see AudioGroup#sendDtmf(int) 15298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 15398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void setDtmfType(int type) { 15498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (isBusy()) { 15598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalStateException("Busy"); 15698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 15798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (type != -1) { 15898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (type < 96 || type > 127) { 15998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("Invalid type"); 16098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 161a7857fbfdfccacb95306e32511f57f1a017b0e31Chia-chi Yeh if (mCodec != null && type == mCodec.type) { 16298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("The type is used by codec"); 16398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mDtmfType = type; 16698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang} 168