[sip-comm-dev] DTMF Infrastructure


#1

Hello,

As I've implemented the sending of DTMF Tones for the IAX stack, and as
it isn't supported by SC yet, I developed the operation set as well as
the necessary for the GUI so that other protocols could use it too (see
the attached files).

Currently, I've designed it as a independent bundle, and modified some
classes (only a few accessor additions ; not included in the attached
files) to get access to the main tabbed pane, so that I can display the
DTMF dialpad (which is a little more rich than a "traditionnal" dialpad)
; but it could be better to integrate it in an already existing GUI
bundle (and that's why I didn't clean the BundleActivator, as it should
disappear).

This is how it works : a protocol provider service must implement the
OperationSetDTMF to send the DTMFTones to a CallParticipant.
In order to let the user send such order, users access the DTMF dialpad
(DialPannel), select the target call participant (below the dialpad) and
press on the buttons. The CallParticipant let access to the Call, to the
ProtocolProviderService, and then to the OperationSetDTMF implementation.
The DTMFPanel implements DTMFDialer, so that another (better) dialpad
could be written without modifying the whole architecture.
The dialpad gets the call participant from the DTMFCPFeeder, which uses
OSGI and SC infrasture (ServiceListener,CallListener,CallChangeListener)
to be notified of new or removed CallParticipants. Thus, a protocol
implementor just has two opsets to implement when he wants to be taken
in account by the Feeder : OperationSetBasicTelephony and OperationSetDTMF.

Feel free to modify it or tell me if you find a way to make it better,
so that it might be integrated in SC in the future (once it's really
needed).

Sincerely,

Jean-Marie HEITZ

DTMFDialer.java (695 Bytes)

DTMFTone.java (2.15 KB)

OperationSetDTMF.java (742 Bytes)

DTMFCPFeeder.java (8.4 KB)

DTMFPanel.java (11 KB)

DTMFPanelActivator.java (1.41 KB)

manifest.mf (411 Bytes)


#2

Hello Jean-Marie,

Nice contribution, thank you!

We've discussed this with Yana and have decided that it is probably
going to be a better idea to implement the UI part in the UI itself.
I've just created the following issue for that.

https://sip-communicator.dev.java.net/issues/show_bug.cgi?id=327

As for the service part of the contribution - we are definitely keeping
it. I find it to be complete and well written so I am committing it.
I've only changed the following few things:

- added SC license on top of all source files
- added javadocs for the DTMF Constructor
- added a hashCode() implementation for DTMF tone.
- slightly changed javadoc for the op set method.
- removed return value for the send dtmf method (if no exception is
thrown while executing the method and there is no reason for it to be
unsuccessful)
- replaces unsupported operation exception in sendDTMFTone() with
OperationFailedException.OPERATION_NOT_SUPPORTED
- replace IllegalArgumentException with ClassCastException in case one
of the arguments does not belong to the underlying implementation.

Once again, these are only minor adjustments. I like your work!

I've committed and acked ur effort.

Thanks for contributing!
Emil

HEITZ Jean-Marie wrote:

···

Hello,

As I've implemented the sending of DTMF Tones for the IAX stack, and as
it isn't supported by SC yet, I developed the operation set as well as
the necessary for the GUI so that other protocols could use it too (see
the attached files).

Currently, I've designed it as a independent bundle, and modified some
classes (only a few accessor additions ; not included in the attached
files) to get access to the main tabbed pane, so that I can display the
DTMF dialpad (which is a little more rich than a "traditionnal" dialpad)
; but it could be better to integrate it in an already existing GUI
bundle (and that's why I didn't clean the BundleActivator, as it should
disappear).

This is how it works : a protocol provider service must implement the
OperationSetDTMF to send the DTMFTones to a CallParticipant.
In order to let the user send such order, users access the DTMF dialpad
(DialPannel), select the target call participant (below the dialpad) and
press on the buttons. The CallParticipant let access to the Call, to the
ProtocolProviderService, and then to the OperationSetDTMF implementation.
The DTMFPanel implements DTMFDialer, so that another (better) dialpad
could be written without modifying the whole architecture.
The dialpad gets the call participant from the DTMFCPFeeder, which uses
OSGI and SC infrasture (ServiceListener,CallListener,CallChangeListener)
to be notified of new or removed CallParticipants. Thus, a protocol
implementor just has two opsets to implement when he wants to be taken
in account by the Feeder : OperationSetBasicTelephony and OperationSetDTMF.

Feel free to modify it or tell me if you find a way to make it better,
so that it might be integrated in SC in the future (once it's really
needed).

Sincerely,

Jean-Marie HEITZ

------------------------------------------------------------------------

package net.java.sip.communicator.service.protocol;
import net.java.sip.communicator.service.protocol.*;
/**
* DTMF Dialer : minimal support for making a DTMF Dialer aware
* of a call participant which could support DTMF Frames
* @author JM HEITZ
*
*/
public interface DTMFDialer
{
    /**
     * Method to take in consideration a CallParticipant for DTMF message
     * @param cpe CallParticipant which could support DTMF
     */
    public void addCallParticipant(CallParticipant cpe);
    /**
     * Method to remove a CallParticipant for possibly sending DTMF message
     * @param cpe the CallParticipant to remove
     */
    public void removeCallParticipant(CallParticipant cpe);
}

------------------------------------------------------------------------

package net.java.sip.communicator.service.protocol;
/**
* Class for representing all the different DTMF tones
* @author JM HEITZ
*
*/
public final class DTMFTone
{
    /**
     * The "A" DTMF Tone
     */
    public static final DTMFTone DTMF_A=new DTMFTone("_A");
    /**
     * The "B" DTMF Tone
     */
    public static final DTMFTone DTMF_B=new DTMFTone("_B");
    /**
     * The "C" DTMF Tone
     */
    public static final DTMFTone DTMF_C=new DTMFTone("_C");
    /**
     * The "D" DTMF Tone
     */
    public static final DTMFTone DTMF_D=new DTMFTone("_D");
    /**
     * The "0" DTMF Tone
     */
    public static final DTMFTone DTMF_0=new DTMFTone("_0");
    /**
     * The "1" DTMF Tone
     */
    public static final DTMFTone DTMF_1=new DTMFTone("_1");
    /**
     * The "2" DTMF Tone
     */
    public static final DTMFTone DTMF_2=new DTMFTone("_2");
    /**
     * The "3" DTMF Tone
     */
    public static final DTMFTone DTMF_3=new DTMFTone("_3");
    /**
     * The "4" DTMF Tone
     */
    public static final DTMFTone DTMF_4=new DTMFTone("_4");
    /**
     * The "5" DTMF Tone
     */
    public static final DTMFTone DTMF_5=new DTMFTone("_5");
    /**
     * The "6" DTMF Tone
     */
    public static final DTMFTone DTMF_6=new DTMFTone("_6");
    /**
     * The "7" DTMF Tone
     */
    public static final DTMFTone DTMF_7=new DTMFTone("_7");
    /**
     * The "8" DTMF Tone
     */
    public static final DTMFTone DTMF_8=new DTMFTone("_8");
    /**
     * The "9" DTMF Tone
     */
    public static final DTMFTone DTMF_9=new DTMFTone("_9");
    /**
     * The "*" DTMF Tone
     */
    public static final DTMFTone DTMF_STAR=new DTMFTone("_STAR");
    /**
     * The "#" DTMF Tone
     */
    public static final DTMFTone DTMF_SHARP=new DTMFTone("_SHARP");

    /**
     *The value of the DTMF tone */
    private final String value;
    /**
     * * @param val
     */
    private DTMFTone(String val)
    {
        this.value=val;
    }
    public boolean equals(Object o)
    {
        if(!(o instanceof DTMFTone))
        {
            return false;
        }
        DTMFTone d=(DTMFTone)(o);
        return d.value.equals(this.value);
    }
}

------------------------------------------------------------------------

package net.java.sip.communicator.service.protocol;
/**
* DTMF Operation Set
* @author JM HEITZ
*
*/
public interface OperationSetDTMF
extends OperationSet
{
/**
* Method for sending a DTMF Tone to a call participant
* @param cpe involved call participant
* @param d involved DTMF tone
* @return operation successfulness
* @throws UnsupportedOperationException when it's not possible to make it now
* @throws NullPointerException when an argument is null
* @throws IllegalArgumentException when a give argument is not of the * implementation expected subclass
*/
    public boolean sendDTMF(CallParticipant cpe,DTMFTone d)
    throws UnsupportedOperationException,
    NullPointerException,
    IllegalArgumentException;
    }

------------------------------------------------------------------------

package net.java.sip.communicator.impl.dtmf;
import org.osgi.framework.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Class developed to feed a DTMFDialer rather "automatically", by using current
* SC infrastructure.
* Meant first as a "proof of work" for information advertisement.
* The idea is the following :
* >register as ServiceListener to get events about ProtocolProviderService
* >get access to the OperationSetDTMF and OperationSetBasicTelephony through
* the ProtocolProviderService
* >register as a CallListener in the OperationSetBasicTelephony to be notified
* about calls
* >register as a CallCHangeListener to be notified about callparticipants of
* a call
* @author JM HEITZ
* TODO : clean start/stop procedure
*/
public class DTMFCPFeeder implements ServiceListener,
CallListener,
CallChangeListener
{
    /**
     * logger for the messages of this class
     */
    private static Logger logger=Logger.getLogger(
            DTMFCPFeeder.class.getName());
    /**
     * register of protocol provider services */
    private Vector v_pps=new Vector();
    /**
     * register of call participants
     */
    private Vector v_cp=new Vector();
    /**
     * register of calls
     */
    private Vector v_call=new Vector();
    /**
     * the DTMFDialer to feed
     */
    private DTMFDialer dtmf=null;
    /**
     * BundleContext for registration
     */
    private BundleContext bc=null;
    public static DTMFCPFeeder getInstance(DTMFDialer dtmf,BundleContext bc)
    {
        if(dtmf!=null && bc !=null)
        {
            try
            {
                return new DTMFCPFeeder(dtmf,bc);
            }
            catch(Exception e)
            {
                System.out.println(e);
                logger.debug(e);
                return null; }
        }
        return null;
    }
    /**
     * Constructor
     * @param dtmf : the dtmf dialer we should feed
     * @param bc bundle context, to access the OSGI framework
     * @throws Exception exception that may occur (especially because bc)
     */
    private DTMFCPFeeder(DTMFDialer dtmf,BundleContext bc) throws Exception
    {
        logger.debug("Feeder init");
        this.dtmf=dtmf;
        this.bc=bc;
        bc.addServiceListener(this);
        logger.debug("addServiceListener");
        ServiceReference []ser= bc.getServiceReferences(
                ProtocolProviderService.class.getName(),null);
        if(ser==null)
        {
            logger.debug("Feeder ser is null");
        }
        if(ser!=null)
        {
            logger.debug("Feeder ser not null : "+ser.length);

            for(int i=0;i<ser.length;i++)
            {
                ProtocolProviderService p=(ProtocolProviderService)(
                        bc.getService(ser[i]));
                logger.debug("Feeder constructor "+p.getProtocolName());
                OperationSet op1=p.getOperationSet(
                        OperationSetBasicTelephony.class);
                OperationSet op2=p.getOperationSet(OperationSetDTMF.class);
                if(op1!=null &&
                        op2!=null)
                {
                    this.addPPS(p);
                }
            }
        }
    }
    /**
     * method for dealing with the addition of a protocol provider service
     * @param p the involved Protocol Provider Service
     */
    private synchronized void addPPS(ProtocolProviderService p)
    {
        logger.debug("addPPS");
        v_pps.add(p);
        OperationSetBasicTelephony tel=(OperationSetBasicTelephony)(
                p.getOperationSet(OperationSetBasicTelephony.class));
        tel.addCallListener(this);
        Iterator i=tel.getActiveCalls();
        while(i.hasNext())
        {
            this.addCall((Call)(i.next()));
        }
    }
    /**
     * method for removing a protocol provider service
     * @param p involved protocol provider service
     */
    private synchronized void removePPS(ProtocolProviderService p)
    {
        logger.debug("removePPS");
        if(v_pps.contains(p))
        {
            v_pps.remove(p);
            OperationSetBasicTelephony tel=(OperationSetBasicTelephony)(
                    p.getOperationSet(OperationSetBasicTelephony.class));
            tel.removeCallListener(this);
            Iterator i=tel.getActiveCalls();
            while(i.hasNext())
            {
                this.removeCall((Call)(i.next()));
            }
        }
    }
    /**
     * method for adding a call
     * @param c involved call
     */
    private synchronized void addCall(Call c)
    {
        v_call.add(c);
        c.addCallChangeListener(this);
        Iterator j=c.getCallParticipants();
        while(j.hasNext())
        {
            this.addParticipant((CallParticipant)(j.next())); }
    }
    /**
     * method for removing a call
     * @param c involved call
     */
    private synchronized void removeCall(Call c)
    {
        if(v_call.contains(c))
        {
            v_call.remove(c);
            c.removeCallChangeListener(this);
            Iterator i=c.getCallParticipants();
            while(i.hasNext())
            {
                this.removeParticipant((CallParticipant)(i.next())); }
        }
    }
    /**
     * method for adding (and feeding) a call participant
     * @param cp involved call participant
     */
    private synchronized void addParticipant(CallParticipant cp)
    {
        v_cp.add(cp);
        dtmf.addCallParticipant(cp);
    }
    /**
     * method for removeing a call participant
     * @param cp involved call participant
     */
    private synchronized void removeParticipant(CallParticipant cp)
    {
        if(v_cp.contains(cp))
        {
            dtmf.removeCallParticipant(cp);
            v_cp.remove(cp);
        }
    } /**
     * method which is called when we are notified a service event * (registration/unregistration of a service)
     * @param e : involved ServiceEvent
     */
    public void serviceChanged(ServiceEvent e)
    {
        logger.debug("Feeder serviceChanged");
        Object src=e.getSource();
        if(src instanceof ProtocolProviderService)
        {
            ProtocolProviderService p=(ProtocolProviderService)(src);
            OperationSet p1=p.getOperationSet(OperationSetBasicTelephony.class);
            OperationSet p2=p.getOperationSet(OperationSetDTMF.class);
            if(p1!=null && p2!=null)
            {
                if(e.getType()==ServiceEvent.REGISTERED)
                {
                    this.addPPS(p);
                }
                if(e.getType()==ServiceEvent.UNREGISTERING)
                {
                    this.removePPS(p);
                }
            } }
    }
    /**
     * method to add an incoming call
     * @param ce : involved call event
     */
    public synchronized void incomingCallReceived(CallEvent ce)
    { logger.debug("Feeder incomingCallReceived");
        this.addCall(ce.getSourceCall());
    }
    /**
     * method to add an outgoing call
     * @param ce : involved call event
     */
    public synchronized void outgoingCallCreated(CallEvent ce)
    { logger.debug("Feeder outgoingCallCreated");
        this.addCall(ce.getSourceCall());
    }
    /**
     * method to remove a call
     * @param ce : involved call event
     */
    public synchronized void callEnded(CallEvent ce)
    {
        logger.debug("Feeder callEnded");
        this.removeCall(ce.getSourceCall());
    }
    /**
     * method to add a call participant
     * @param cpe : involved call participant event
     */
    public synchronized void callParticipantAdded(CallParticipantEvent cpe)
    {
        logger.debug("Feeder callParticipantAdded");
        this.addParticipant(cpe.getSourceCallParticipant()); }
    /**
     * method to remove a call participant
     * @param cpe : involved call participant
     */
    public synchronized void callParticipantRemoved(CallParticipantEvent cpe)
    {
        logger.debug("Feeder callParticipantRemoved");
        this.removeParticipant(cpe.getSourceCallParticipant());
    }
    /**
     * method called when there is a change in the call state ; does nothing
     * currently
     */
    public synchronized void callStateChanged(CallChangeEvent cce)
    {
        logger.debug("Feeder callStateChanged");
        return;
    }
}

------------------------------------------------------------------------

package net.java.sip.communicator.impl.dtmf;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
/**
* A class developed to factorize DTMF button actions
* Could become a DTMFPanel internal class
* @author JM HEITZ
*
*/
class DTMFActionListener implements ActionListener
{
    /**
     * A logger to pass the message (especially for operation failures)
     */
    private static Logger logger=
        Logger.getLogger(DTMFActionListener.class.getName());
    /**
     * involved DTMFPanel
     */
    private DTMFPanel dp;
    /**
     * DTMFTone to generate
     */
    private DTMFTone d;
    /**
     * Constructor
     * @param dp involved panel
     * @param d involved tone
     */
    public DTMFActionListener(DTMFPanel dp,DTMFTone d)
    {
        this.dp=dp;
        this.d=d;
    }
    /**
     * Action to perform : do our best to send the DTMF message
     */
    public void actionPerformed(ActionEvent e)
    {
        try
        {
            CallParticipant cp=dp.getCurrentCallParticipant();
            ProtocolProviderService pps=
                cp.getProtocolProvider();
            OperationSet os=pps.getOperationSet(OperationSetDTMF.class);
            if(os==null)
            {
                logger.debug("OS null");
                return;
            }
            OperationSetDTMF dtmf=(OperationSetDTMF)(os);
            if(dtmf.sendDTMF(cp, d)==false)
            {
                logger.debug("DTMF Generation failed");
            }
        }
        catch(Exception f)
        {
            logger.debug(f.toString());

        }
    }
}
/**
* DTMF Call Panel - a DTMF dialpad
* @author JM HEITZ
*
*/
public class DTMFPanel extends JPanel //we can be displayed
implements DTMFDialer,//to be usable from outside (using OSGI framework)
ItemListener //to get the currently selected CallParticipant
{
    /**
     * logger for the messages of this class
     */
    Logger logger=Logger.getLogger(DTMFPanel.class.getName());
    /**
     * Hashtable to store the interested call participants, using their unique
     * ParticipantID as key * Hashtable<String,CallParticipant>
     */
    private Hashtable hcp=new Hashtable();
    /**
     * Combo box to let the user select the call participant he wants to send
     * a DTMF Message
     */
    private JComboBox jcb=new JComboBox();
    /**
     * Auxilliary jpanel to put the buttons into
     */
    private JPanel jp=new JPanel();
    /**
     * DTMF_0 button
     */
    private JButton jb_0=new JButton("0");
    /**
     * DTMF_1 button
     */
    private JButton jb_1=new JButton("1");
    /**
     * DTMF_2 button
     */
    private JButton jb_2=new JButton("2");
    /**
     * DTMF_3 button
     */
    private JButton jb_3=new JButton("3");
    /**
     * DTMF_4 button
     */
    private JButton jb_4=new JButton("4");
    /**
     * DTMF_5 button
     */
    private JButton jb_5=new JButton("5");
    /**
     * DTMF_6 button
     */
    private JButton jb_6=new JButton("6");
    /**
     * DTMF_7 button
     */
    private JButton jb_7=new JButton("7");
    /**
     * DTMF_8 button
     */
    private JButton jb_8=new JButton("8");
    /**
     * DTMF_9 button
     */
    private JButton jb_9=new JButton("9");
    /**
     * DTMF_A button
     */
    private JButton jb_A=new JButton("A");
    /**
     * DTMF_B button
     */
    private JButton jb_B=new JButton("B");
    /**
     * DTMF_C button
     */
    private JButton jb_C=new JButton("C");
    /**
     * DTMF_D button
     */
    private JButton jb_D=new JButton("D");
    /**
     * DTMF_* button
     */
    private JButton jb_STAR=new JButton("*");
    /**
     * DTMF_# button
     */
    private JButton jb_SHARP=new JButton("#");
    /**
     * Currently selected call participant
     */
    private CallParticipant currentCP=null;
    /**
     * Accessor
     * @return the current CallParticipant
     */
    public synchronized CallParticipant getCurrentCallParticipant()
    {
        return currentCP; }
    /**
     * Method for adding a participant which can deal with a DTMF Tone
     * @param cp involved call participant
     */
    public synchronized void addCallParticipant(CallParticipant cp)
    {

        if(!hcp.containsKey(cp.getParticipantID()))
        {
            hcp.put(cp.getParticipantID(),cp);
            jcb.addItem(cp.getParticipantID());
        }
    }
    /**
     * Method for removing a participant which had been added
     * @param cp the pariticpant to remove
     */
    public synchronized void removeCallParticipant(CallParticipant cp)
    {
        if(hcp.containsKey(cp.getParticipantID()))
        {
            hcp.remove(cp.getParticipantID());
            jcb.removeItem(cp.getParticipantID());
            if(hcp.size()==0)//when there is no participant left, disable
                //the dialpad
            {
                jb_0.setEnabled(false);
                jb_1.setEnabled(false);
                jb_2.setEnabled(false);
                jb_3.setEnabled(false);
                jb_4.setEnabled(false);
                jb_5.setEnabled(false);
                jb_6.setEnabled(false);
                jb_7.setEnabled(false);
                jb_8.setEnabled(false);
                jb_9.setEnabled(false);
                jb_A.setEnabled(false);
                jb_B.setEnabled(false);
                jb_C.setEnabled(false);
                jb_D.setEnabled(false);
                jb_STAR.setEnabled(false);
                jb_SHARP.setEnabled(false);
            }
        }
    }
    /**
     * Method to determine if we should enable/disable the dialpad when * the targetted call participant change
     */
    public synchronized void itemStateChanged(ItemEvent e) {
        System.out.println(e);
        if(e.getStateChange()==ItemEvent.DESELECTED)
        {
            String s=(String)(e.getItem());
            if(currentCP!=null && currentCP.getParticipantID().equals(s))
            {
                currentCP=null;
                jb_0.setEnabled(false);
                jb_1.setEnabled(false);
                jb_2.setEnabled(false);
                jb_3.setEnabled(false);
                jb_4.setEnabled(false);
                jb_5.setEnabled(false);
                jb_6.setEnabled(false);
                jb_7.setEnabled(false);
                jb_8.setEnabled(false);
                jb_9.setEnabled(false);
                jb_A.setEnabled(false);
                jb_B.setEnabled(false);
                jb_C.setEnabled(false);
                jb_D.setEnabled(false);
                jb_STAR.setEnabled(false);
                jb_SHARP.setEnabled(false);
            }
        }
        if(e.getStateChange()==ItemEvent.SELECTED)
        {
            String pid=(String)(e.getItem());
            currentCP=(CallParticipant)(hcp.get(pid));
            ProtocolProviderService pps=currentCP.getProtocolProvider();
            OperationSet os=null;
            if(pps!=null)
            {
                os=pps.getOperationSet(OperationSetDTMF.class);
            }
            else
            {
                logger.debug("DTMF PPS NULL");
            }
            if(os==null)
            {
                jb_0.setEnabled(false);
                jb_1.setEnabled(false);
                jb_2.setEnabled(false);
                jb_3.setEnabled(false);
                jb_4.setEnabled(false);
                jb_5.setEnabled(false);
                jb_6.setEnabled(false);
                jb_7.setEnabled(false);
                jb_8.setEnabled(false);
                jb_9.setEnabled(false);
                jb_A.setEnabled(false);
                jb_B.setEnabled(false);
                jb_C.setEnabled(false);
                jb_D.setEnabled(false);
                jb_STAR.setEnabled(false);
                jb_SHARP.setEnabled(false);
            }
            else
            {
                jb_0.setEnabled(true);
                jb_1.setEnabled(true);
                jb_2.setEnabled(true);
                jb_3.setEnabled(true);
                jb_4.setEnabled(true);
                jb_5.setEnabled(true);
                jb_6.setEnabled(true);
                jb_7.setEnabled(true);
                jb_8.setEnabled(true);
                jb_9.setEnabled(true);
                jb_A.setEnabled(true);
                jb_B.setEnabled(true);
                jb_C.setEnabled(true);
                jb_D.setEnabled(true);
                jb_STAR.setEnabled(true);
                jb_SHARP.setEnabled(true);
            }
        }
    }
    /**
     * Constructor
     *
     */
    public DTMFPanel()
    { jcb.addItemListener(this);
        jp.setLayout(new GridLayout(4,4));
        jb_0.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_0));
        jb_1.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_1));
        jb_2.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_2));
        jb_3.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_3));
        jb_4.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_4));
        jb_5.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_5));
        jb_6.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_6));
        jb_7.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_7));
        jb_8.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_8));
        jb_9.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_9));
        jb_A.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_A));
        jb_B.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_B));
        jb_C.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_C));
        jb_D.addActionListener(new DTMFActionListener(this,DTMFTone.DTMF_D));
        jb_STAR.addActionListener(
                new DTMFActionListener(this,DTMFTone.DTMF_STAR));
        jb_SHARP.addActionListener(
                new DTMFActionListener(this,DTMFTone.DTMF_SHARP));
        jp.add(jb_1);
        jp.add(jb_2);
        jp.add(jb_3);
        jp.add(jb_A);
        jp.add(jb_4);
        jp.add(jb_5);
        jp.add(jb_6);
        jp.add(jb_B);
        jp.add(jb_7);
        jp.add(jb_8);
        jp.add(jb_9);
        jp.add(jb_C);
        jp.add(jb_STAR);
        jp.add(jb_0);
        jp.add(jb_SHARP);
        jp.add(jb_D);
        //as we shouldn't have participants at this point
        //disable the dialpad
        jb_0.setEnabled(false);
        jb_1.setEnabled(false);
        jb_2.setEnabled(false);
        jb_3.setEnabled(false);
        jb_4.setEnabled(false);
        jb_5.setEnabled(false);
        jb_6.setEnabled(false);
        jb_7.setEnabled(false);
        jb_8.setEnabled(false);
        jb_9.setEnabled(false);
        jb_A.setEnabled(false);
        jb_B.setEnabled(false);
        jb_C.setEnabled(false);
        jb_D.setEnabled(false);
        jb_STAR.setEnabled(false);
        jb_SHARP.setEnabled(false);
        this.setLayout(new BorderLayout());
        this.add(jp,BorderLayout.CENTER);
        this.add(jcb,BorderLayout.SOUTH);
    }
}

------------------------------------------------------------------------

package net.java.sip.communicator.impl.dtmf;
import java.util.*;

import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.DTMFDialer;
import net.java.sip.communicator.impl.gui.main.*;
import org.osgi.framework.*;
//Class which should not survive to SC integration
//TODO : make a clean SC integration
public class DTMFPanelActivator implements BundleActivator
{
    private BundleContext bc=null;
    private DTMFPanel dtmf=new DTMFPanel();
    private MainFrame mf;
    private MainTabbedPane mtp;
    private ServiceRegistration sr=null;

    public void start(BundleContext bc)
    {

        System.out.println("ACT1");
        System.out.flush();
        this.bc=bc;
        System.out.println("ACT2");
        System.out.flush();
        //sr=bc.registerService(DTMFDialer.class.getName(),
          // dtmf, new Properties());
        DTMFCPFeeder feed=DTMFCPFeeder.getInstance(dtmf,bc);
        mf=MainFrame.getMainFrame();
        System.out.println("ACT3");
        System.out.flush();
        mtp=mf.getTabbedPane();
        System.out.println("ACT4");
        System.out.flush();
        mtp.addTab("DTMF",dtmf);
        System.out.println("ACT5");
        System.out.flush();

    }

    public void stop(BundleContext bc)
    {

        int idx=mtp.indexOfComponent(dtmf);
        mtp.removeTabAt(idx);
        if(sr!=null)
        {
        sr.unregister();
        }

    }
}

------------------------------------------------------------------------

Bundle-Activator: net.java.sip.communicator.impl.dtmf.DTMFPanelActivator
Bundle-Name: IAX Stack Bundle
Bundle-Vendor: JM HEITZ
Bundle-Version: 0.0.1
Import-Package: org.osgi.framework,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.event,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.util,
net.java.sip.communicator.impl.gui.main,
javax.swing

------------------------------------------------------------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net