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.media;
018
019/**
020 * Represents a payload type.
021 *
022 * @author Alvaro Saurin
023 */
024public class PayloadType {
025
026    public static final String NODENAME = "payload-type";
027    
028    public static int MAX_FIXED_PT = 95;
029
030    public static int INVALID_PT = 65535;
031
032    private int id;
033
034    private String name;
035
036    private int channels;
037
038    /**
039     * Constructor with Id, name and number of channels
040     *
041     * @param id       The identifier
042     * @param name     A name
043     * @param channels The number of channels
044     */
045    public PayloadType(int id, final String name, int channels) {
046        super();
047        this.id = id;
048        this.name = name;
049        this.channels = channels;
050    }
051
052    /**
053     * Default constructor.
054     */
055    public PayloadType() {
056        this(INVALID_PT, null, 1);
057    }
058
059    /**
060     * Constructor with Id and name
061     *
062     * @param id   The identification
063     * @param name A name
064     */
065    public PayloadType(int id, String name) {
066        this(id, name, 1);
067    }
068
069    /**
070     * Copy constructor
071     *
072     * @param pt The other payload type.
073     */
074    public PayloadType(PayloadType pt) {
075        this(pt.getId(), pt.getName(), pt.getChannels());
076    }
077
078    /**
079     * Get the ID.
080     *
081     * @return the ID
082     */
083    public int getId() {
084        return id;
085    }
086
087    /**
088     * Set the ID.
089     *
090     * @param id ID
091     */
092    public void setId(int id) {
093        this.id = id;
094    }
095
096    /**
097     * Get the printable name.
098     *
099     * @return printable name for the payload type
100     */
101    public String getName() {
102        return name;
103    }
104
105    /**
106     * Set the printable name.
107     *
108     * @param name the printable name
109     */
110    public void setName(String name) {
111        this.name = name;
112    }
113
114    /**
115     * Get the number of channels used by this payload type.
116     *
117     * @return the number of channels
118     */
119    public int getChannels() {
120        return channels;
121    }
122
123    /**
124     * Set the numer of channels for a payload type.
125     *
126     * @param channels The number of channels
127     */
128    public void setChannels(int channels) {
129        this.channels = channels;
130    }
131
132    /**
133     * Return true if the Payload type is not valid
134     *
135     * @return true if the payload type is invalid
136     */
137    public boolean isNull() {
138        if (getId() == INVALID_PT) {
139            return true;
140        }
141        else if (getName() == null) {
142            return true;
143        }
144        return false;
145    }
146
147    /*
148      * (non-Javadoc)
149      *
150      * @see java.lang.Object#hashCode()
151      */
152    public int hashCode() {
153        final int PRIME = 31;
154        int result = 1;
155        result = PRIME * result + getChannels();
156        result = PRIME * result + getId();
157        result = PRIME * result + (getName() == null ? 0 : getName().hashCode());
158        return result;
159    }
160
161    /*
162      * (non-Javadoc)
163      *
164      * @see java.lang.Object#equals(java.lang.Object)
165      */
166    public boolean equals(Object obj) {
167        if (this == obj) {
168            return true;
169        }
170        if (obj == null) {
171            return false;
172        }
173        if (getClass() != obj.getClass()) {
174            return false;
175        }
176        final PayloadType other = (PayloadType) obj;
177        if (getChannels() != other.getChannels()) {
178            return false;
179        }
180        if (getId() != other.getId()) {
181            return false;
182        }
183
184        // Compare names only for dynamic payload types
185        if (getId() > MAX_FIXED_PT) {
186            if (getName() == null) {
187                if (other.getName() != null) {
188                    return false;
189                }
190            }
191            else if (!getName().equals(other.getName())) {
192                return false;
193            }
194        }
195
196        return true;
197    }
198    
199    /**
200     * Returns the XML element name of the element.
201     *
202     * @return the XML element name of the element.
203     */
204    public static String getElementName() {
205        return NODENAME;
206    }
207    
208    public String toXML() {
209        StringBuilder buf = new StringBuilder();
210
211            buf.append("<").append(getElementName()).append(" ");
212
213            // We covert here the payload type to XML
214            if (this.getId() != PayloadType.INVALID_PT) {
215                buf.append(" id=\"").append(this.getId()).append("\"");
216            }
217            if (this.getName() != null) {
218                buf.append(" name=\"").append(this.getName()).append("\"");
219            }
220            if (this.getChannels() != 0) {
221                buf.append(" channels=\"").append(this.getChannels()).append("\"");
222            }
223            if (getChildAttributes() != null) {
224                buf.append(getChildAttributes());
225            }
226            buf.append("/>");
227        
228        return buf.toString();
229    }
230    
231    protected String getChildAttributes() {
232        StringBuilder buf = new StringBuilder();
233        if (this instanceof PayloadType.Audio) {
234            PayloadType.Audio pta = (PayloadType.Audio) this;
235
236            buf.append(" clockrate=\"").append(pta.getClockRate()).append("\" ");
237        }
238        
239        return buf.toString();
240    }
241
242    /**
243     * Audio payload type.
244     */
245    public static class Audio extends PayloadType {
246
247        private int clockRate;
248
249        /**
250         * Constructor with all the attributes of an Audio payload type
251         *
252         * @param id       The identifier
253         * @param name     The name assigned to this payload type
254         * @param channels The number of channels
255         * @param rate     The clock rate
256         */
257        public Audio(int id, String name, int channels, int rate) {
258            super(id, name, channels);
259            clockRate = rate;
260        }
261
262        /**
263         * Constructor with all the attributes of an Audio payload type
264         *
265         * @param id       The identifier
266         * @param name     The name assigned to this payload type
267         * @param rate     The clock rate
268         */
269        public Audio(int id, String name, int rate) {
270            super(id, name);
271            clockRate = rate;
272        }
273
274        /**
275         * Empty constructor.
276         */
277        public Audio() {
278            super();
279            clockRate = 0;
280        }
281
282        /**
283         * Constructor with Id and name
284         *
285         * @param id   the Id for the payload type
286         * @param name the name of the payload type
287         */
288        public Audio(int id, String name) {
289            super(id, name);
290            clockRate = 0;
291        }
292
293        /**
294         * Copy constructor
295         *
296         * @param pt the other payload type
297         */
298        public Audio(PayloadType pt) {
299            super(pt);
300            clockRate = 0;
301        }
302
303        /**
304         * Copy constructor
305         *
306         * @param pt the other payload type
307         */
308        public Audio(PayloadType.Audio pt) {
309            super(pt);
310            clockRate = pt.getClockRate();
311        }
312
313        /**
314         * Get the sampling clockRate for a payload type
315         *
316         * @return The sampling clockRate
317         */
318        public int getClockRate() {
319            return clockRate;
320        }
321
322        /**
323         * Set tha sampling clockRate for a playload type.
324         *
325         * @param rate The sampling clockRate
326         */
327        public void setClockRate(int rate) {
328            clockRate = rate;
329        }
330
331        /*
332           * (non-Javadoc)
333           *
334           * @see java.lang.Object#hashCode()
335           */
336        public int hashCode() {
337            final int PRIME = 31;
338            int result = super.hashCode();
339            result = PRIME * result + getClockRate();
340            return result;
341        }
342
343        /*
344           * (non-Javadoc)
345           *
346           * @see java.lang.Object#equals(java.lang.Object)
347           */
348        public boolean equals(Object obj) {
349            if (this == obj) {
350                return true;
351            }
352            if (!super.equals(obj)) {
353                return false;
354            }
355            if (getClass() != obj.getClass()) {
356                return false;
357            }
358            final Audio other = (Audio) obj;
359            if (getClockRate() != other.getClockRate()) {
360                return false;
361            }
362            return true;
363        }
364    }
365}