Implements OperationSetIncomingDTMF for XMPP, wired to receive events via RTP/RFC4733.

maven
Boris Grozev 12 years ago
parent 683947fd17
commit d9b5ba9037

@ -1401,4 +1401,32 @@ && getConference().isJitsiVideobridge())
}
return this.jitsiVideobridge;
}
/**
* {@inheritDoc}
*
* Implements
* {@link net.java.sip.communicator.service.protocol.event.DTMFListener#toneReceived(net.java.sip.communicator.service.protocol.event.DTMFReceivedEvent)}
*
* Forwards DTMF events to the <tt>IncomingDTMF</tt> operation set, setting
* this <tt>Call</tt> as the source.
*/
@Override
public void toneReceived(DTMFReceivedEvent evt)
{
OperationSetIncomingDTMF opSet
= getProtocolProvider()
.getOperationSet(OperationSetIncomingDTMF.class);
if (opSet != null && opSet instanceof OperationSetIncomingDTMFJabberImpl)
{
// Re-fire the event using this Call as the source.
((OperationSetIncomingDTMFJabberImpl) opSet).toneReceived(
new DTMFReceivedEvent(
this,
evt.getValue(),
evt.getDuration(),
evt.getStart()));
}
}
}

@ -0,0 +1,61 @@
/*
* 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.jabber;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import java.util.*;
/**
* Implements <tt>OperationSetIncomingDTMF</tt> for the jabber protocol.
*
* @author Boris Grozev
*/
public class OperationSetIncomingDTMFJabberImpl
implements OperationSetIncomingDTMF,
DTMFListener
{
private final Set<DTMFListener> listeners = new HashSet<DTMFListener>();
/**
* {@inheritDoc}
*
* Implements
* {@link net.java.sip.communicator.service.protocol.OperationSetIncomingDTMF#addDTMFListener(net.java.sip.communicator.service.protocol.event.DTMFListener)}
*/
@Override
public void addDTMFListener(DTMFListener listener)
{
listeners.add(listener);
}
/**
* {@inheritDoc}
*
* Implements
* {@link net.java.sip.communicator.service.protocol.OperationSetIncomingDTMF#removeDTMFListener(net.java.sip.communicator.service.protocol.event.DTMFListener)}
*/
@Override
public void removeDTMFListener(DTMFListener listener)
{
listeners.remove(listener);
}
/**
* {@inheritDoc}
*
* Implements
* {@link net.java.sip.communicator.service.protocol.event.DTMFListener#toneReceived(net.java.sip.communicator.service.protocol.event.DTMFReceivedEvent)}
*/
@Override
public void toneReceived(DTMFReceivedEvent evt)
{
for (DTMFListener listener : listeners)
listener.toneReceived(evt);
}
}

@ -1831,10 +1831,14 @@ protected void initialize(String screenname,
}
// init DTMF
OperationSetDTMFJabberImpl operationSetDTMFSip
OperationSetDTMFJabberImpl operationSetDTMF
= new OperationSetDTMFJabberImpl(this);
addSupportedOperationSet(
OperationSetDTMF.class, operationSetDTMFSip);
OperationSetDTMF.class, operationSetDTMF);
addSupportedOperationSet(
OperationSetIncomingDTMF.class,
new OperationSetIncomingDTMFJabberImpl());
addJingleFeatures();

@ -101,11 +101,11 @@ public synchronized void startSendingDTMF(CallPeer callPeer, DTMFTone tone)
}
// If the account is configured to use RTP DTMF method and the call
// does not manage telephone events. Then, we log it for futur
// does not manage telephone events. Then, we log it for future
// debugging.
if(this.dtmfMethod == DTMFMethod.RTP_DTMF && !isRFC4733Active(cp))
{
logger.debug("RTP DTMF used without telephon-event capacities");
logger.debug("RTP DTMF used without telephone-event capacity");
}
((AudioMediaStream)cp.getMediaHandler().getStream(MediaType.AUDIO))

@ -10,8 +10,8 @@
import net.java.sip.communicator.service.protocol.event.*;
/**
* An <tt>OperationSet</tt> that allows us to receive DMF tones through
* this protocol provider.
* An <tt>OperationSet</tt> that allows us to receive DTMF tones through
* this protocol provider. Only supports SIP INFO.
*
* @author Damian Minkov
*/

@ -289,7 +289,7 @@ public boolean processResponse(ResponseEvent responseEvent)
return processed;
}
/*
/**
* Receives dtmf info requests.
*/
@Override

@ -8,14 +8,13 @@
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import org.jitsi.service.protocol.*;
/**
* <tt>DTMFReceivedEvent</tt>s indicate reception of a DTMF tone.
*
* @author Damian Minkov
* @author Boris Grozev
*/
public class DTMFReceivedEvent
extends EventObject
@ -28,30 +27,77 @@ public class DTMFReceivedEvent
/**
* The tone.
*/
private DTMFTone value = null;
private final DTMFTone value;
/**
* The duration.
*/
private long duration;
private final long duration;
/**
* Whether this <tt>DTMFReceivedEvent</tt> represents the start of reception
* of a tone (if <tt>true</tt>), the end of reception of a tone (if
* <tt>false</tt>), or the reception of a tone with a given duration (if
* <tt>null</tt>).
*/
private final Boolean start;
/**
* Creates a <tt>MessageReceivedEvent</tt> representing reception of the
* <tt>source</tt> message received from the specified <tt>from</tt>
* contact.
*
* @param source the <tt>Message</tt> whose reception this event represents.
* @param value dmtf tone value
* @param duration duration of the DTMF tone
* @param source the source of the event.
* @param value dmtf tone value.
* @param start whether this event represents the start of reception (if
* <tt>true</tt>), the end of reception (if <tt>false</tt>) or the reception
* of a tone with a given direction (if <tt>null</tt>).
*/
public DTMFReceivedEvent(ProtocolProviderService source,
public DTMFReceivedEvent(Object source,
DTMFTone value,
boolean start)
{
this(source, value, -1, start);
}
/**
* Creates a <tt>MessageReceivedEvent</tt> representing reception of the
* <tt>source</tt> message received from the specified <tt>from</tt>
* contact.
*
* @param source the source of the event.
* @param value dmtf tone value.
* @param duration duration of the DTMF tone.
*/
public DTMFReceivedEvent(Object source,
DTMFTone value,
long duration)
{
this(source, value, duration, null);
}
/**
* Creates a <tt>MessageReceivedEvent</tt> representing reception of the
* <tt>source</tt> message received from the specified <tt>from</tt>
* contact.
*
* @param source the source of the event.
* @param value dmtf tone value.
* @param duration duration of the DTMF tone.
* @param start whether this event represents the start of reception (if
* <tt>true</tt>), the end of reception (if <tt>false</tt>) or the reception
* of a tone with a given direction (if <tt>null</tt>).
*/
public DTMFReceivedEvent(Object source,
DTMFTone value,
long duration,
Boolean start)
{
super(source);
this.value = value;
this.duration = duration;
this.start = start;
}
/**
@ -71,4 +117,16 @@ public long getDuration()
{
return duration;
}
/**
* Returns the value of the <tt>start</tt> attribute of this
* <tt>DTMFReceivedEvent</tt>, which indicates whether this
* <tt>DTMFReceivedEvent</tt> represents the start of reception of a tone
* (if <tt>true</tt>), the end of reception of a tone (if <tt>false</tt>),
* or the reception of a tone with a given duration (if <tt>null</tt>).
*/
public Boolean getStart()
{
return start;
}
}

@ -27,7 +27,7 @@
* A utility class implementing media control code shared between current
* telephony implementations. This class is only meant for use by protocol
* implementations and should not be accessed by bundles that are simply using
* the telephony functionalities.
* the telephony functionality.
*
* @param <T> the peer extension class like for example <tt>CallPeerSipImpl</tt>
* or <tt>CallPeerJabberImpl</tt>
@ -1806,6 +1806,11 @@ public void setMediaHandler(MediaHandler mediaHandler)
if (srtpListener != null)
this.mediaHandler.removeSrtpListener(srtpListener);
this.mediaHandler.removeVideoListener(videoStreamVideoListener);
// We intentionally do not remove our Call from the list of
// DTMF listeners. It should stay there as long as the
// MediaHandler is used by at least one CallPeer/CPMH.
//this.mediaHandler.removeDtmfListener(getPeer().getCall());
}
this.mediaHandler = mediaHandler;
@ -1843,6 +1848,7 @@ public void setMediaHandler(MediaHandler mediaHandler)
if (srtpListener != null)
this.mediaHandler.addSrtpListener(srtpListener);
this.mediaHandler.addVideoListener(videoStreamVideoListener);
this.mediaHandler.addDtmfListener(getPeer().getCall());
}
}
}

@ -12,6 +12,7 @@
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.event.DTMFListener;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.device.*;
import org.jitsi.service.neomedia.event.*;
@ -41,7 +42,8 @@ public abstract class MediaAwareCall<
V extends ProtocolProviderService>
extends AbstractCall<T, V>
implements CallPeerListener,
PropertyChangeListener
PropertyChangeListener,
DTMFListener
{
/**
* The name of the property of <tt>MediaAwareCall</tt> the value of which
@ -960,4 +962,16 @@ public void setConference(CallConference conference)
{
super.setConference(conference);
}
/**
* {@inheritDoc}
*
* Implements
* {@link net.java.sip.communicator.service.protocol.event.DTMFListener#toneReceived(net.java.sip.communicator.service.protocol.event.DTMFReceivedEvent)}
*/
@Override
public void toneReceived(DTMFReceivedEvent evt)
{
// Stub
}
}

@ -11,7 +11,9 @@
import java.util.*;
import java.util.List;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.OperationFailedException;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.event.DTMFListener;
import net.java.sip.communicator.util.*;
import org.jitsi.service.neomedia.*;
@ -19,6 +21,7 @@
import org.jitsi.service.neomedia.device.*;
import org.jitsi.service.neomedia.event.*;
import org.jitsi.service.neomedia.format.*;
import org.jitsi.service.protocol.*;
import org.jitsi.util.event.*;
/**
@ -184,6 +187,18 @@ public void securityTurnedOn(
private final List<SrtpListener> srtpListeners
= new LinkedList<SrtpListener>();
/**
* The set of listeners in the application (<tt>Jitsi</tt>) which are to
* be notified of DTMF events.
*/
private final Set<DTMFListener> dtmfListeners
= new HashSet<DTMFListener>();
/**
* The listener registered to receive DTMF events from {@link #audioStream}.
*/
private final MyDTMFListener dtmfListener = new MyDTMFListener();
/**
* The <tt>SimpleAudioLeveListener</tt> that this instance sets on its
* {@link #audioStream} if {@link #streamAudioLevelListeners} is not empty
@ -444,6 +459,27 @@ void addSrtpListener(SrtpListener listener)
}
}
/**
* Adds a <tt>DTMFListener</tt> which will be notified when DTMF events
* are received from the <tt>MediaHandler</tt>'s audio stream.
* @param listener the listener to add.
*/
void addDtmfListener(DTMFListener listener)
{
if (listener != null)
dtmfListeners.add(listener);
}
/**
* Removes a <tt>DTMFListener</tt> from the set of listeners to be notified
* for DTMF events from this <tt>MediaHandler</tt>'s audio steam.
* @param listener the listener to remove.
*/
void removeDtmfListener(DTMFListener listener)
{
dtmfListeners.remove(listener);
}
/**
* Adds a specific <tt>SimpleAudioLevelListener</tt> to the list of
* <tt>SimpleAudioLevelListener</tt>s to be notified about changes in the
@ -1201,6 +1237,8 @@ private void setAudioStream(AudioMediaStream audioStream)
this.audioStream.removePropertyChangeListener(
streamPropertyChangeListener);
this.audioStream.removeDTMFListener(dtmfListener);
this.audioStream.close();
}
@ -1240,6 +1278,8 @@ private void setAudioStream(AudioMediaStream audioStream)
streamAudioLevelListener);
}
}
this.audioStream.addDTMFListener(dtmfListener);
}
else
{
@ -1495,4 +1535,53 @@ private void setVideoStream(VideoMediaStream videoStream)
}
}
}
/**
* Implements a <tt>libjitsi</tt> <tt>DTMFListener</tt>, which receives
* events from an <tt>AudioMediaStream</tt>, translate them into
* <tt>Jitsi</tt> events (<tt>DTMFReceivedEvent</tt>s) and forward them to
* any registered listeners.
*/
private class MyDTMFListener
implements org.jitsi.service.neomedia.event.DTMFListener
{
/**
* {@inheritDoc}
*/
@Override
public void dtmfToneReceptionStarted(DTMFToneEvent dtmfToneEvent)
{
fireEvent(
new DTMFReceivedEvent(
this,
DTMFTone.getDTMFTone(dtmfToneEvent.getDtmfTone().getValue()),
true));
}
/**
* {@inheritDoc}
*/
@Override
public void dtmfToneReceptionEnded(DTMFToneEvent dtmfToneEvent)
{
fireEvent(
new DTMFReceivedEvent(
this,
DTMFTone.getDTMFTone(dtmfToneEvent.getDtmfTone().getValue()),
false));
}
/**
* Sends an <tt>DTMFReceivedEvent</tt> to all listeners.
* @param event the event to send.
*/
private void fireEvent(DTMFReceivedEvent event)
{
for (net.java.sip.communicator.service.protocol.event.DTMFListener
listener : dtmfListeners)
{
listener.toneReceived(event);
}
}
}
}

Loading…
Cancel
Save