Bug 239388 - [api] Add capability to send DTMF with the ecf.telephony.call API
Summary: [api] Add capability to send DTMF with the ecf.telephony.call API
Status: RESOLVED WONTFIX
Alias: None
Product: ECF
Classification: RT
Component: ecf.providers (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows All
: P3 enhancement (vote)
Target Milestone: 2.1.0   Edit
Assignee: ecf.core-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2008-07-03 00:02 EDT by Mike Greenawalt CLA
Modified: 2014-02-12 15:11 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Greenawalt CLA 2008-07-03 00:02:52 EDT
I am a committer with the Eclipse Voice Tools Project (VTP), and I want to use the ECF Skype provider to build the interface between the VTP and a Voice XML Browser. This use does not require a UI, it makes a simple phone call programmatically. However, while working with a voice application, there are numerous circumstances where DTMF (dialtones) are needed to be sent. Although the Skype4Java code allows sending DTMF, there is currently no provision in the Call API for this. If such a capability is not present, then the ECF provider will not be useful to VTP, so this is critical to our project.

I have had conversation with Scott about this, and I append snippets of that conversation here with his ideas:

"I can see that the skype4java API does have DTMF capability (i.e. Call.sendDTMF(...)), but the ECF Call API currently does not.

But I think such an interface would be easy to define additions to the ECF call API to support using this capability of the Skype adapter.  For example,  a new interface such as:

public interface ICallSessionDTMFAdapter {

public void sendDTMF(DTMF dtmf) throws ECFException;

}

...which could be an adapter for the ICallSession interface...e.g.

ICallSession callSession = ...

ICallSessionDTMFAdapter dtmfAdapter = (ICallSessionDTMFAdapter) callSession.getAdapter(ICallSessionDTMFAdapter.class);
// if adapter is non-null then use it
dtmfAdapter.sendDTMF(new DTMF("911"));

This would, of course, mean adding at least this new interface (ICallSessionDTMFAdapter) to the API, but this is easy to do for ECF 2.1.  And providing the impl for skype provider (and others that support such functions), but that doesn't seem like a big deal. "

The sendDTMF method should have two versions, one that accepts a string of 0-9#*, and a second that also accepts an int which is used as a delay (in ms) to be inserted between each digit as it is sent. We find that some browsers need more time to recognize the digits, so need to control the interval.

Thank you for considering this change.
Comment 1 Scott Lewis CLA 2008-07-03 11:37:50 EDT
Setting target milestone, adding api to subject, and assigning to myself.
Comment 2 Scott Lewis CLA 2008-07-04 01:58:38 EDT
(In reply to comment #1)
> Setting target milestone, adding api to subject, and assigning to myself.
> 

I've created a new interface in org.eclipse.ecf.telephony.call API plugin named org.eclipse.ecf.telephony.call.dtmf.IDTMFCallSessionAdapter:

/**
 * ICallSession adapter for sending DTMF codes during a call session.
 */
public interface IDTMFCallSessionAdapter {

	public static class DTMF implements Serializable {
		private static final long serialVersionUID = -4664398793204446391L;
		private static final char TYPE_0_CHAR = '0';
		private static final char TYPE_1_CHAR = '1';
		private static final char TYPE_2_CHAR = '2';
		private static final char TYPE_3_CHAR = '3';
		private static final char TYPE_4_CHAR = '4';
		private static final char TYPE_5_CHAR = '5';
		private static final char TYPE_6_CHAR = '6';
		private static final char TYPE_7_CHAR = '7';
		private static final char TYPE_8_CHAR = '8';
		private static final char TYPE_9_CHAR = '9';
		private static final char TYPE_ASTERISK_CHAR = '*';
		private static final char TYPE_SHARP_CHAR = '#';

		private final transient char type;

		protected DTMF(char c) {
			this.type = c;
		}

		public static final DTMF TYPE_0 = new DTMF(TYPE_0_CHAR);
		public static final DTMF TYPE_1 = new DTMF(TYPE_1_CHAR);
		public static final DTMF TYPE_2 = new DTMF(TYPE_2_CHAR);
		public static final DTMF TYPE_3 = new DTMF(TYPE_3_CHAR);
		public static final DTMF TYPE_4 = new DTMF(TYPE_4_CHAR);
		public static final DTMF TYPE_5 = new DTMF(TYPE_5_CHAR);
		public static final DTMF TYPE_6 = new DTMF(TYPE_6_CHAR);
		public static final DTMF TYPE_7 = new DTMF(TYPE_7_CHAR);
		public static final DTMF TYPE_8 = new DTMF(TYPE_8_CHAR);
		public static final DTMF TYPE_9 = new DTMF(TYPE_9_CHAR);
		public static final DTMF TYPE_SHARP = new DTMF(TYPE_SHARP_CHAR);
		public static final DTMF TYPE_ASTERISK = new DTMF(TYPE_ASTERISK_CHAR);

		public static DTMF fromChar(char c) {
			return new DTMF(c);
		}

		public char toChar() {
			return type;
		}

		// This is to make sure that subclasses don't screw up these methods
		public final boolean equals(Object that) {
			return super.equals(that);
		}

		public final int hashCode() {
			return super.hashCode();
		}

		// For serialization
		private static int nextOrdinal = 0;

		private final int ordinal = nextOrdinal++;

		private static final DTMF[] VALUES = {TYPE_0, TYPE_1, TYPE_2, TYPE_3, TYPE_4, TYPE_5, TYPE_6, TYPE_7, TYPE_8, TYPE_9, TYPE_SHARP, TYPE_ASTERISK};

		/**
		 * @return Object
		 * @throws ObjectStreamException not thrown by this implementation.
		 */
		Object readResolve() throws ObjectStreamException {
			return VALUES[ordinal];
		}

	}

	/**
	 * Send DTMF to receiver.
	 * 
	 * @param command the DTMF command to send.  Must not be <code>null</code>.
	 * @throws CallException if problem with sending (e.g. no longer connected).
	 */
	public void sendDTMF(DTMF command) throws CallException;

}


The API is actually the single method sendDTMF(DTMF command).

The way this is used is that this adapter is accessed via an instance of ICallSession...e.g.

// get ICallSession instance by connecting
ICallSession callSession = ...
// Then see if IDTMFCallSessionAdapter is available for provider
IDTMFCallSessionAdapter dtmf = (IDTMFCallSessionAdapter) callSession.getAdapter(IDTMFCallSessionAdapter);
// if it'snon null then we use it
if (dtmf != null) {
  dtmf.sendDTMF(DTMF.TYPE_SHARP);
} else {
// DTMF not available with this provider
}

And that's it.  Any comments about this API?  I will be writing some test code for it soon (or Michael if you would like to do this it would be very helpful).

I've committed this addition to HEAD, and have implemented the functionality for the Skype provider using the skype4java Call.sendDTMF capability.

Comment 3 Scott Lewis CLA 2014-02-12 15:11:05 EST
Please reopen if this bug if resources become available to move it forward.  Would like to see work on the ECF support of dtmf.