/* * Mobicents, Communications Middleware * * Copyright (c) 2008, Red Hat Middleware LLC or third-party * contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Middleware LLC. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * * Boston, MA 02110-1301 USA */ package org.mobicents.media.server.impl.resource.dtmf; import org.mobicents.media.Buffer; import org.mobicents.media.Format; import org.mobicents.media.server.impl.AbstractSource; import org.mobicents.media.server.impl.rtp.RtpHeader; import org.mobicents.media.server.impl.rtp.sdp.AVProfile; import org.mobicents.media.server.spi.SyncSource; import org.mobicents.media.server.spi.resource.DtmfGenerator; /** * * @author kulikov * @author amit bhayani */ public class Rfc2833GeneratorImpl extends AbstractSource implements DtmfGenerator { private byte digit; private String sDigit; private boolean endOfEvent = false; // Volume range from 0 to 63 private int volume = 0; // Min duration = 40ms and max = 500ms private int duration = 50; private int mediaPackets = 0; private RtpHeader rtpHeader = new RtpHeader(); private int heartBeat = 20; private int eventDuration = 160; public Rfc2833GeneratorImpl(String name, SyncSource syncSource) { super(name); setSyncSource(syncSource); } private byte encode(String digit) { if (digit.equals("1")) { return 1; } else if (digit.equals("2")) { return 2; } else if (digit.equals("3")) { return 3; } else if (digit.equals("4")) { return 4; } else if (digit.equals("5")) { return 5; } else if (digit.equals("6")) { return 6; } else if (digit.equals("7")) { return 7; } else if (digit.equals("8")) { return 8; } else if (digit.equals("9")) { return 9; } else if (digit.equals("0")) { return 0; } else if (digit.equals("*")) { return 10; } else if (digit.equals("#")) { return 11; } else if (digit.equals("A")) { return 12; } else if (digit.equals("B")) { return 13; } else if (digit.equals("C")) { return 14; } else if (digit.equals("D")) { return 15; } else { throw new IllegalArgumentException("The Digit " + digit + " is not identified"); } } public void setDigit(String digit) { this.sDigit = digit; } public String getDigit() { return this.sDigit; } public void setToneDuration(int duration) { if (duration < 40) { throw new IllegalArgumentException("Duration cannot be less than 40ms"); } this.duration = duration; } public int getToneDuration() { return this.duration; } public void setVolume(int volume) { if (volume < 0 || volume > 36) { throw new IllegalArgumentException("Volume cannot be less than 0db or greater than 63db"); } this.volume = (int)volume; } public int getVolume() { return this.volume; } @Override public void start() { if (this.sDigit != null) { this.digit = encode(this.sDigit); mediaPackets = duration / heartBeat + 2; super.start(); } } @Override public void stop() { } public Format[] getFormats() { return Rfc2833DetectorImpl.FORMATS; } public void evolve(Buffer buffer, long timestamp, long seq) { boolean marker = true; endOfEvent = false; if (seq == (mediaPackets - 3)) { endOfEvent = true; } rtpHeader.setMarker(marker); buffer.setHeader(rtpHeader); marker = false; byte[] data = (byte[]) buffer.getData(); data[0] = digit; data[1] = endOfEvent ? (byte) (volume | 0x80) : (byte) (volume & 0x7f); data[2] = (byte) (eventDuration >> 8); data[3] = (byte) (eventDuration); eventDuration = eventDuration + 160; buffer.setOffset(0); buffer.setLength(4); buffer.setFormat(AVProfile.DTMF); buffer.setSequenceNumber(seq); buffer.setTimeStamp(timestamp); if (seq == mediaPackets) { buffer.setEOM(true); } } }