AudioStream.java revision 32e106b7bdd57c82ee67705871f6116d92bce79b
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
3032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * usage includes one for each endpoints. For other combinations, users should
3132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * 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
3732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * back after the modification is done.
3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh *
3932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @see AudioGroup
4032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * @hide
41363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */
42363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class AudioStream extends RtpStream {
43363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private AudioCodec mCodec;
44363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private int mDtmfType = -1;
45363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private AudioGroup mGroup;
46363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
48363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Creates an AudioStream on the given local address. Note that the local
49363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * port is assigned automatically to conform with RFC 3550.
50363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
51363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param address The network address of the local host to bind to.
52363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws SocketException if the address cannot be bound or a problem
53363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *     occurs during binding.
54363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
55363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public AudioStream(InetAddress address) throws SocketException {
56363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        super(address);
57363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
58363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
59363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
6032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Returns {@code true} if the stream has already joined an
6132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * {@link AudioGroup}.
62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    @Override
64363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public final boolean isBusy() {
65363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mGroup != null;
66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
67363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
68363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
69363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Returns the joined {@link AudioGroup}.
70363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
7132e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public AudioGroup getGroup() {
72363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mGroup;
73363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
74363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
75363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
76363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Joins an {@link AudioGroup}. Each stream can join only one group at a
77363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * time. The group can be changed by passing a different one or removed
78363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * by calling this method with {@code null}.
79363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
80363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param group The AudioGroup to join or {@code null} to leave.
81363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is not properly configured.
82363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @see AudioGroup
83363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
84363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public void join(AudioGroup group) {
85363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (mGroup == group) {
86363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            return;
87363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
88363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (mGroup != null) {
89363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            mGroup.remove(this);
90363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            mGroup = null;
91363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
92363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (group != null) {
9332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            group.add(this, mCodec, mDtmfType);
94363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            mGroup = group;
95363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
96363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
97363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
98363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
9932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Sets the {@link AudioCodec}.
100363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
101363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param codec The AudioCodec to be used.
10232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * @throws IllegalArgumentException if its type is used by DTMF.
103363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is busy.
104363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
10532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    public void setCodec(AudioCodec codec) {
106363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (isBusy()) {
107363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalStateException("Busy");
108363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
10932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh        if (codec.type == mDtmfType) {
110363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalArgumentException("The type is used by DTMF");
111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
112363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mCodec = codec;
113363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
114363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
115363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
116363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits.
117363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * The primary usage is to send digits to the remote gateway to perform
118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * certain tasks, such as second-stage dialing. According to RFC 2833, the
119363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * RTP payload type for DTMF is assigned dynamically, so it must be in the
120363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * range of 96 and 127. One can use {@code -1} to disable DTMF and free up
121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * the previous assigned value. This method cannot be called when the stream
122363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * already joined an {@link AudioGroup}.
123363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param type The RTP payload type to be used or {@code -1} to disable it.
125363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalArgumentException if the type is invalid or used by codec.
126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is busy.
127363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @see AudioGroup#sendDtmf(int)
128363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public void setDtmfType(int type) {
130363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (isBusy()) {
131363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalStateException("Busy");
132363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
133363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (type != -1) {
134363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            if (type < 96 || type > 127) {
135363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang                throw new IllegalArgumentException("Invalid type");
136363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            }
13732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh            if (type == mCodec.type) {
138363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang                throw new IllegalArgumentException("The type is used by codec");
139363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            }
140363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
141363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mDtmfType = type;
142363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
143363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang}
144