001/** 002 * 003 * Copyright 2003-2005 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.jingle.packet; 018 019import org.jivesoftware.smack.packet.PacketExtension; 020import org.jivesoftware.smackx.jingle.media.PayloadType; 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.Iterator; 025import java.util.List; 026 027/** 028 * Jingle content description. 029 * 030 * @author Alvaro Saurin <alvaro.saurin@gmail.com> 031 */ 032public abstract class JingleContentDescription implements PacketExtension { 033 034 // static 035 036 public static final String NODENAME = "description"; 037 038 // non-static 039 040 private final List<JinglePayloadType> payloads = new ArrayList<JinglePayloadType>(); 041 042 /** 043 * Creates a content description.. 044 */ 045 public JingleContentDescription() { 046 super(); 047 } 048 049 /** 050 * Returns the XML element name of the element. 051 * 052 * @return the XML element name of the element. 053 */ 054 public String getElementName() { 055 return NODENAME; 056 } 057 058 /** 059 * Return the namespace. 060 * 061 * @return The namespace 062 */ 063 public abstract String getNamespace(); 064 065 /** 066 * Adds a audio payload type to the packet. 067 * 068 * @param pt the audio payload type to add. 069 */ 070 public void addJinglePayloadType(final JinglePayloadType pt) { 071 synchronized (payloads) { 072 payloads.add(pt); 073 } 074 } 075 076 /** 077 * Adds a list of payloads to the packet. 078 * 079 * @param pts the payloads to add. 080 */ 081 public void addAudioPayloadTypes(final List<PayloadType.Audio> pts) { 082 synchronized (payloads) { 083 Iterator<PayloadType.Audio> ptIter = pts.iterator(); 084 while (ptIter.hasNext()) { 085 PayloadType.Audio pt = ptIter.next(); 086 addJinglePayloadType(new JinglePayloadType.Audio(pt)); 087 } 088 } 089 } 090 091 /** 092 * Returns an Iterator for the audio payloads in the packet. 093 * 094 * @return an Iterator for the audio payloads in the packet. 095 */ 096 public Iterator<JinglePayloadType> getJinglePayloadTypes() { 097 return Collections.unmodifiableList(getJinglePayloadTypesList()).iterator(); 098 } 099 100 /** 101 * Returns a list for the audio payloads in the packet. 102 * 103 * @return a list for the audio payloads in the packet. 104 */ 105 public ArrayList<JinglePayloadType> getJinglePayloadTypesList() { 106 synchronized (payloads) { 107 return new ArrayList<JinglePayloadType>(payloads); 108 } 109 } 110 111 /** 112 * Return the list of Payload types contained in the description. 113 * 114 * @return a list of PayloadType.Audio 115 */ 116 public ArrayList<PayloadType.Audio> getAudioPayloadTypesList() { 117 ArrayList<PayloadType.Audio> result = new ArrayList<PayloadType.Audio>(); 118 Iterator<JinglePayloadType> jinglePtsIter = getJinglePayloadTypes(); 119 120 while (jinglePtsIter.hasNext()) { 121 JinglePayloadType jpt = jinglePtsIter.next(); 122 if (jpt instanceof JinglePayloadType.Audio) { 123 JinglePayloadType.Audio jpta = (JinglePayloadType.Audio) jpt; 124 result.add((PayloadType.Audio)jpta.getPayloadType()); 125 } 126 } 127 128 return result; 129 } 130 131 /** 132 * Returns a count of the audio payloads in the Jingle packet. 133 * 134 * @return the number of audio payloads in the Jingle packet. 135 */ 136 public int getJinglePayloadTypesCount() { 137 synchronized (payloads) { 138 return payloads.size(); 139 } 140 } 141 142 /** 143 * Convert a Jingle description to XML. 144 * 145 * @return a string with the XML representation 146 */ 147 public String toXML() { 148 StringBuilder buf = new StringBuilder(); 149 150 synchronized (payloads) { 151 if (payloads.size() > 0) { 152 buf.append("<").append(getElementName()); 153 buf.append(" xmlns=\"").append(getNamespace()).append("\" >"); 154 155 Iterator<JinglePayloadType> pt = payloads.listIterator(); 156 while (pt.hasNext()) { 157 JinglePayloadType pte = pt.next(); 158 buf.append(pte.toXML()); 159 } 160 buf.append("</").append(getElementName()).append(">"); 161 } 162 } 163 164 return buf.toString(); 165 } 166 167 /** 168 * Jingle audio description 169 */ 170 public static class Audio extends JingleContentDescription { 171 172 public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp"; 173 174 public Audio() { 175 super(); 176 } 177 178 /** 179 * Utility constructor, with a JinglePayloadType 180 */ 181 public Audio(final JinglePayloadType pt) { 182 super(); 183 addJinglePayloadType(pt); 184 } 185 186 public String getNamespace() { 187 return NAMESPACE; 188 } 189 } 190 191 /** 192 * A payload type, contained in a descriptor. 193 * 194 * @author Alvaro Saurin 195 */ 196 public static class JinglePayloadType { 197 198 public static final String NODENAME = "payload-type"; 199 200 private PayloadType payload; 201 202 /** 203 * Create a payload type. 204 * 205 * @param payload the payload 206 */ 207 public JinglePayloadType(final PayloadType payload) { 208 super(); 209 this.payload = payload; 210 } 211 212 /** 213 * Create an empty payload type. 214 */ 215 public JinglePayloadType() { 216 this(null); 217 } 218 219 /** 220 * Returns the XML element name of the element. 221 * 222 * @return the XML element name of the element. 223 */ 224 public static String getElementName() { 225 return NODENAME; 226 } 227 228 /** 229 * Get the payload represented. 230 * 231 * @return the payload 232 */ 233 public PayloadType getPayloadType() { 234 return payload; 235 } 236 237 /** 238 * Set the payload represented. 239 * 240 * @param payload the payload to set 241 */ 242 public void setPayload(final PayloadType payload) { 243 this.payload = payload; 244 } 245 246 protected String getChildAttributes() { 247 return null; 248 } 249 250 public String toXML() { 251 StringBuilder buf = new StringBuilder(); 252 253 if (payload != null) { 254 buf.append("<").append(getElementName()).append(" "); 255 256 // We covert here the payload type to XML 257 if (payload.getId() != PayloadType.INVALID_PT) { 258 buf.append(" id=\"").append(payload.getId()).append("\""); 259 } 260 if (payload.getName() != null) { 261 buf.append(" name=\"").append(payload.getName()).append("\""); 262 } 263 if (payload.getChannels() != 0) { 264 buf.append(" channels=\"").append(payload.getChannels()).append("\""); 265 } 266 if (getChildAttributes() != null) { 267 buf.append(getChildAttributes()); 268 } 269 buf.append("/>"); 270 } 271 return buf.toString(); 272 } 273 274 /** 275 * Audio payload type element 276 */ 277 public static class Audio extends JinglePayloadType { 278 public Audio(final PayloadType.Audio audio) { 279 super(audio); 280 } 281 282 protected String getChildAttributes() { 283 StringBuilder buf = new StringBuilder(); 284 PayloadType pt = getPayloadType(); 285 if (pt instanceof PayloadType.Audio) { 286 PayloadType.Audio pta = (PayloadType.Audio) pt; 287 288 buf.append(" clockrate=\"").append(pta.getClockRate()).append("\" "); 289 } 290 return buf.toString(); 291 } 292 } 293 } 294}