diff options
author | Damian Minkov <damencho@jitsi.org> | 2012-02-01 12:38:14 +0000 |
---|---|---|
committer | Damian Minkov <damencho@jitsi.org> | 2012-02-01 12:38:14 +0000 |
commit | 8e66e5a9db51c6f68d04575c9bafb9648be63f2d (patch) | |
tree | e43b59a71e4baa51c4cae3b96d1b527102dd5b91 /src/net/java/sip/communicator/impl | |
parent | ee69f66fe49880758a639a3336df1b32e7175c5d (diff) | |
download | jitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.zip jitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.tar.gz jitsi-8e66e5a9db51c6f68d04575c9bafb9648be63f2d.tar.bz2 |
Implements receiving of sip INFO dtmf tones.
Diffstat (limited to 'src/net/java/sip/communicator/impl')
4 files changed, 258 insertions, 2 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java index c8ad9d9..9bd2878 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetDTMFSipImpl.java @@ -134,4 +134,13 @@ public class OperationSetDTMFSipImpl return false; } + + /** + * Returns DTMFInfo mode implementation. + * @return DTMFInfo mode implementation. + */ + DTMFInfo getDtmfModeInfo() + { + return dtmfModeInfo; + } } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java new file mode 100644 index 0000000..506ecbb --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetIncomingDTMFSipImpl.java @@ -0,0 +1,63 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.sip; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +/** + * An <tt>OperationSet</tt> that allows us to receive DMF tones through + * this protocol provider. + * + * @author Damian Minkov + */ +public class OperationSetIncomingDTMFSipImpl + implements OperationSetIncomingDTMF +{ + /** + * The parent provider. + */ + private ProtocolProviderServiceSipImpl provider; + + /** + * The send DTMF operation set holding dtmf implementations. + */ + private OperationSetDTMFSipImpl opsetDTMFSip; + + /** + * Creates operation set. + * @param provider the parent provider + * @param opsetDTMFSip the dtmf implementation. + */ + OperationSetIncomingDTMFSipImpl(ProtocolProviderServiceSipImpl provider, + OperationSetDTMFSipImpl opsetDTMFSip) + { + this.provider = provider; + + this.opsetDTMFSip = opsetDTMFSip; + } + + /** + * Registers the specified DTMFListener with this provider so that it could + * be notified when incoming DTMF tone is received. + * @param listener the listener to register with this provider. + * + */ + public void addDTMFListener(DTMFListener listener) + { + this.opsetDTMFSip.getDtmfModeInfo().addDTMFListener(listener); + } + + /** + * Removes the specified listener from the list of DTMF listeners. + * @param listener the listener to unregister. + */ + public void removeDTMFListener(DTMFListener listener) + { + this.opsetDTMFSip.getDtmfModeInfo().removeDTMFListener(listener); + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index c4e224d..4eeadf7 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -443,9 +443,15 @@ public class ProtocolProviderServiceSipImpl new OperationSetTelephonyConferencingSipImpl(this)); // init DTMF (from JM Heitz) + OperationSetDTMFSipImpl operationSetDTMFSip + = new OperationSetDTMFSipImpl(this); addSupportedOperationSet( - OperationSetDTMF.class, - new OperationSetDTMFSipImpl(this)); + OperationSetDTMF.class, operationSetDTMFSip); + + addSupportedOperationSet( + OperationSetIncomingDTMF.class, + new OperationSetIncomingDTMFSipImpl( + this, operationSetDTMFSip)); boolean isDesktopStreamingDisabled = SipActivator.getConfigurationService() diff --git a/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java b/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java index 1c29751..612030f 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/dtmf/DTMFInfo.java @@ -8,6 +8,7 @@ package net.java.sip.communicator.impl.protocol.sip.dtmf; import gov.nist.javax.sip.header.*; +import java.io.*; import java.text.*; import java.util.*; @@ -17,6 +18,7 @@ import javax.sip.message.*; import net.java.sip.communicator.impl.protocol.sip.*; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; /** @@ -59,6 +61,12 @@ public class DTMFInfo private final ProtocolProviderServiceSipImpl pps; /** + * A list of listeners registered for dtmf tone events. + */ + private final List<DTMFListener> dtmfListeners = + new LinkedList<DTMFListener>(); + + /** * Constructor * * @param pps the SIP Protocol provider service @@ -277,4 +285,174 @@ public class DTMFInfo } return processed; } + + /* + * Receives dtmf info requests. + */ + public boolean processRequest(RequestEvent requestEvent) + { + Request request = requestEvent.getRequest(); + + ContentTypeHeader contentTypeHeader + = (ContentTypeHeader) + request.getHeader(ContentTypeHeader.NAME); + + if ((contentTypeHeader != null) + && CONTENT_TYPE.equalsIgnoreCase( + contentTypeHeader.getContentType()) + && CONTENT_SUB_TYPE.equalsIgnoreCase( + contentTypeHeader.getContentSubType())) + { + try + { + byte[] value; + Object valueObj = request.getContent(); + + if(valueObj instanceof String) + value = ((String)valueObj).getBytes("UTF-8"); + else if(valueObj instanceof byte[]) + value = (byte[])valueObj; + else + { + logger.error("Unknown content type"); + return false; + } + + Properties prop = new Properties(); + prop.load(new ByteArrayInputStream(value)); + + String signal = prop.getProperty("Signal"); + String durationStr = prop.getProperty("Duration"); + + DTMFTone tone = DTMFTone.getDTMFTone(signal); + + if(tone == null) + { + logger.warn("Unknown tone received: " + tone); + return false; + } + + long duration = 0; + try + { + duration = Long.parseLong(durationStr); + } + catch(NumberFormatException ex) + { + logger.warn("Error parsing duration:" + durationStr, ex); + } + + // fire event + fireToneEvent(tone, duration); + } + catch(IOException ioe) + {} + + Response responseOK; + + try + { + responseOK = pps.getMessageFactory().createResponse( + Response.OK, requestEvent.getRequest()); + } + catch (ParseException ex) + { + //What else could we do apart from logging? + logger.warn("Failed to create OK for incoming INFO request", ex); + return false; + } + + try + { + SipStackSharing.getOrCreateServerTransaction(requestEvent). + sendResponse(responseOK); + } + catch(TransactionUnavailableException ex) + { + if (logger.isInfoEnabled()) + logger.info("Failed to respond to an incoming " + +"transactionless INFO request"); + if (logger.isTraceEnabled()) + logger.trace("Exception was:", ex); + return false; + } + catch (InvalidArgumentException ex) + { + //What else could we do apart from logging? + logger.warn("Failed to send OK for incoming INFO request", ex); + return false; + } + catch (SipException ex) + { + //What else could we do apart from logging? + logger.warn("Failed to send OK for incoming INFO request", ex); + return false; + } + + return true; + } + + return false; + } + + /** + * Fire event to interested listeners. + * @param tone to go into event. + * @param duration of the tone. + */ + private void fireToneEvent(DTMFTone tone, long duration) + { + Collection<DTMFListener> listeners; + synchronized (this.dtmfListeners) + { + listeners = new ArrayList<DTMFListener>(this.dtmfListeners); + } + + DTMFReceivedEvent evt = new DTMFReceivedEvent(pps, tone, duration); + + if (logger.isDebugEnabled()) + logger.debug("Dispatching DTMFTone Listeners=" + listeners.size() + + " evt=" + evt); + + try + { + for (DTMFListener listener : listeners) + { + listener.toneReceived(evt); + } + } + catch (Throwable e) + { + logger.error("Error delivering dtmf tone", e); + } + } + + /** + * Registers the specified DTMFListener with this provider so that it could + * be notified when incoming DTMF tone is received. + * @param listener the listener to register with this provider. + * + */ + public void addDTMFListener(DTMFListener listener) + { + synchronized (dtmfListeners) + { + if (!dtmfListeners.contains(listener)) + { + dtmfListeners.add(listener); + } + } + } + + /** + * Removes the specified listener from the list of DTMF listeners. + * @param listener the listener to unregister. + */ + public void removeDTMFListener(DTMFListener listener) + { + synchronized (dtmfListeners) + { + dtmfListeners.remove(listener); + } + } } |