001/** 002 * 003 * Copyright 2003-2006 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.jingleold.mediaimpl.jmf; 018 019import java.io.IOException; 020import java.net.ServerSocket; 021import java.util.logging.Level; 022import java.util.logging.Logger; 023 024import javax.media.MediaLocator; 025 026import org.jivesoftware.smackx.jingleold.JingleSession; 027import org.jivesoftware.smackx.jingleold.media.JingleMediaSession; 028import org.jivesoftware.smackx.jingleold.media.PayloadType; 029import org.jivesoftware.smackx.jingleold.nat.TransportCandidate; 030 031/** 032 * This Class implements a complete JingleMediaSession. 033 * It should be used to transmit and receive audio captured from the Mic. 034 * This Class should be automatically controlled by JingleSession. 035 * But you could also use in any VOIP application. 036 * For better NAT Traversal support this implementation don't support only receive or only transmit. 037 * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() 038 * 039 * @author Thiago Camargo 040 */ 041public class AudioMediaSession extends JingleMediaSession { 042 043 private static final Logger LOGGER = Logger.getLogger(AudioMediaSession.class.getName()); 044 045 private AudioChannel audioChannel; 046 047 /** 048 * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates. 049 * 050 * @param payloadType Payload of the jmf 051 * @param remote the remote information. The candidate that the jmf will be sent to. 052 * @param local the local information. The candidate that will receive the jmf 053 * @param locator media locator 054 */ 055 public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, 056 final TransportCandidate local, String locator, JingleSession jingleSession) { 057 super(payloadType, remote, local, locator == null ? "dsound://" : locator,jingleSession); 058 initialize(); 059 } 060 061 /** 062 * Initialize the Audio Channel to make it able to send and receive audio. 063 */ 064 @Override 065 public void initialize() { 066 067 String ip; 068 String localIp; 069 int localPort; 070 int remotePort; 071 072 if (this.getLocal().getSymmetric() != null) { 073 ip = this.getLocal().getIp(); 074 localIp = this.getLocal().getLocalIp(); 075 localPort = getFreePort(); 076 remotePort = this.getLocal().getSymmetric().getPort(); 077 078 LOGGER.fine(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); 079 080 } 081 else { 082 ip = this.getRemote().getIp(); 083 localIp = this.getLocal().getLocalIp(); 084 localPort = this.getLocal().getPort(); 085 remotePort = this.getRemote().getPort(); 086 } 087 088 audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this); 089 } 090 091 /** 092 * Starts transmission and for NAT Traversal reasons start receiving also. 093 * 094 * @deprecated use {@link #startTransmit()} instead. 095 */ 096 @Deprecated 097 public void startTrasmit() { 098 startTransmit(); 099 } 100 101 /** 102 * Starts transmission and for NAT Traversal reasons start receiving also. 103 */ 104 @Override 105 public void startTransmit() { 106 audioChannel.start(); 107 } 108 109 /** 110 * Set transmit activity. If the active is true, the instance should transmit. 111 * If it is set to false, the instance should pause transmit. 112 * 113 * @param active active state 114 * @deprecated use {@link #setTransmit(boolean)} instead. 115 */ 116 @Deprecated 117 public void setTrasmit(boolean active) { 118 setTransmit(active); 119 } 120 121 /** 122 * Set transmit activity. If the active is true, the instance should transmit. 123 * If it is set to false, the instance should pause transmit. 124 * 125 * @param active active state 126 */ 127 @Override 128 public void setTransmit(boolean active) { 129 audioChannel.setTrasmit(active); 130 } 131 132 /** 133 * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 134 */ 135 @Override 136 public void startReceive() { 137 // Do nothing 138 } 139 140 /** 141 * Stops transmission and for NAT Traversal reasons stop receiving also. 142 * 143 * @deprecated use {@link #stopTransmit()} instead. 144 */ 145 @Deprecated 146 public void stopTrasmit() { 147 stopTransmit(); 148 } 149 150 /** 151 * Stops transmission and for NAT Traversal reasons stop receiving also. 152 */ 153 @Override 154 public void stopTransmit() { 155 if (audioChannel != null) 156 audioChannel.stop(); 157 } 158 159 /** 160 * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 161 */ 162 @Override 163 public void stopReceive() { 164 // Do nothing 165 } 166 167 /** 168 * Obtain a free port we can use. 169 * 170 * @return A free port number. 171 */ 172 protected int getFreePort() { 173 ServerSocket ss; 174 int freePort = 0; 175 176 for (int i = 0; i < 10; i++) { 177 freePort = (int) (10000 + Math.round(Math.random() * 10000)); 178 freePort = freePort % 2 == 0 ? freePort : freePort + 1; 179 try { 180 ss = new ServerSocket(freePort); 181 freePort = ss.getLocalPort(); 182 ss.close(); 183 return freePort; 184 } 185 catch (IOException e) { 186 LOGGER.log(Level.WARNING, "exception", e); 187 } 188 } 189 try { 190 ss = new ServerSocket(0); 191 freePort = ss.getLocalPort(); 192 ss.close(); 193 } 194 catch (IOException e) { 195 LOGGER.log(Level.WARNING, "exception", e); 196 } 197 return freePort; 198 } 199 200}