package org.mobicents.media.server.impl.resource.ivr; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mobicents.media.Format; import org.mobicents.media.server.ConnectionFactory; import org.mobicents.media.server.EndpointImpl; import org.mobicents.media.server.impl.clock.TimerImpl; import org.mobicents.media.server.impl.dsp.DspFactory; import org.mobicents.media.server.impl.dsp.audio.g711.ulaw.DecoderFactory; import org.mobicents.media.server.impl.dsp.audio.g711.ulaw.EncoderFactory; import org.mobicents.media.server.impl.resource.DemuxFactory; import org.mobicents.media.server.impl.resource.MuxFactory; import org.mobicents.media.server.impl.resource.audio.AudioPlayerEvent; import org.mobicents.media.server.impl.resource.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.audio.RecorderEvent; import org.mobicents.media.server.impl.resource.audio.RecorderFactory; import org.mobicents.media.server.impl.resource.dtmf.Rfc2833DetectorFactory; import org.mobicents.media.server.impl.resource.dtmf.Rfc2833GeneratorFactory; import org.mobicents.media.server.impl.rtp.RtpFactory; import org.mobicents.media.server.impl.rtp.sdp.AVProfile; import org.mobicents.media.server.resource.ChannelFactory; import org.mobicents.media.server.resource.PipeFactory; import org.mobicents.media.server.spi.Connection; import org.mobicents.media.server.spi.ConnectionMode; import org.mobicents.media.server.spi.NotificationListener; import org.mobicents.media.server.spi.Timer; import org.mobicents.media.server.spi.events.NotifyEvent; import org.mobicents.media.server.spi.resource.AudioPlayer; import org.mobicents.media.server.spi.resource.DtmfDetector; import org.mobicents.media.server.spi.resource.DtmfGenerator; import org.mobicents.media.server.spi.resource.Recorder; /** * * @author amit bhayani * */ public class IvrTest { private int localPort1 = 9201; private int localPort2 = 9202; private Timer timer; private EndpointImpl sender; private EndpointImpl ivrEnp; private RtpFactory rtpFactory1, rtpFactory2; private Rfc2833DetectorFactory rfc2833fact; private DemuxFactory deMuxFact; private RecorderFactory recFact; private ChannelFactory rxChannFact; private Semaphore semaphore; private boolean started = false; private boolean end_of_media = false; private boolean failed = false; private boolean stopped = false; private boolean completed = false; private boolean receivedEvent = false; public IvrTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() throws Exception { timer = new TimerImpl(); HashMap<Integer, Format> rtpmap = new HashMap(); rtpmap.put(0, AVProfile.PCMU); rtpmap.put(101, AVProfile.DTMF); rtpFactory1 = new RtpFactory(); rtpFactory1.setBindAddress("localhost"); rtpFactory1.setLocalPort(localPort1); rtpFactory1.setTimer(timer); rtpFactory1.setFormatMap(rtpmap); rtpFactory1.start(); rtpFactory2 = new RtpFactory(); rtpFactory2.setBindAddress("localhost"); rtpFactory2.setLocalPort(localPort2); rtpFactory2.setTimer(timer); rtpFactory2.setFormatMap(rtpmap); rtpFactory2.start(); Hashtable<String, RtpFactory> rtpFactories1 = new Hashtable<String, RtpFactory>(); rtpFactories1.put("audio", rtpFactory1); Hashtable<String, RtpFactory> rtpFactories2 = new Hashtable<String, RtpFactory>(); rtpFactories2.put("audio", rtpFactory2); // preparing g711: ALaw encoder, ULAW decoder EncoderFactory encoderFactory = new EncoderFactory(); DecoderFactory decoderFactory = new DecoderFactory(); // group codecs into list ArrayList list = new ArrayList(); list.add(encoderFactory); list.add(decoderFactory); // creating dsp factory with g711 encoder/decoder DspFactory dspFactory = new DspFactory(); dspFactory.setName("dsp"); dspFactory.setCodecFactories(list); // Create Rfc2833DetectorFactory rfc2833fact = new Rfc2833DetectorFactory(); rfc2833fact.setName("Rfc2833DetectorFactory"); // Create a Demux Factory deMuxFact = new DemuxFactory("DeMux"); // creating component list ArrayList components = new ArrayList(); components.add(rfc2833fact); components.add(deMuxFact); components.add(dspFactory); // define pipes // Exhaust for Rx channel PipeFactory p1 = new PipeFactory(); p1.setInlet(null); p1.setOutlet("dsp"); PipeFactory p2 = new PipeFactory(); p2.setInlet("DeMux"); p2.setOutlet("Rfc2833DetectorFactory"); PipeFactory p3 = new PipeFactory(); p3.setInlet("dsp"); p3.setOutlet("DeMux"); PipeFactory p4 = new PipeFactory(); p4.setInlet("DeMux"); p4.setOutlet(null); ArrayList pipes = new ArrayList(); pipes.add(p1); pipes.add(p2); pipes.add(p3); pipes.add(p4); rxChannFact = new ChannelFactory(); rxChannFact.start(); rxChannFact.setComponents(components); rxChannFact.setPipes(pipes); ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setRxChannelFactory(rxChannFact); // Create RecorderFactory - sink for endpoint recFact = new RecorderFactory(); recFact.setName("RecorderFactory"); ivrEnp = new EndpointImpl("/ivr/test/dtmf"); ivrEnp.setSinkFactory(recFact); ivrEnp.setTimer(timer); ivrEnp.setConnectionFactory(connectionFactory); ivrEnp.setRtpFactory(rtpFactories1); // start IVREndpoint ivrEnp.start(); /** * Components declared for Ann Endpoint */ // Mux MuxFactory muxFact = new MuxFactory("Mux"); // Rfc2833Generator Rfc2833GeneratorFactory rfc2833GenFact = new Rfc2833GeneratorFactory(); rfc2833GenFact.setName("Rfc2833GeneratorFactory"); List annConponents = new ArrayList(); annConponents.add(muxFact); annConponents.add(rfc2833GenFact); annConponents.add(dspFactory); PipeFactory p5 = new PipeFactory(); p5.setInlet(null); p5.setOutlet("Mux"); PipeFactory p6 = new PipeFactory(); p6.setInlet("Rfc2833GeneratorFactory"); p6.setOutlet("Mux"); PipeFactory p7 = new PipeFactory(); p7.setInlet("Mux"); p7.setOutlet("dsp"); PipeFactory p8 = new PipeFactory(); p8.setInlet("dsp"); p8.setOutlet(null); List annPipes = new ArrayList(); annPipes.add(p5); annPipes.add(p6); annPipes.add(p7); annPipes.add(p8); // creating transparent channels ChannelFactory channelFactory = new ChannelFactory(); channelFactory.start(); channelFactory.setComponents(annConponents); channelFactory.setPipes(annPipes); ConnectionFactory connectionFactory1 = new ConnectionFactory(); connectionFactory1.setTxChannelFactory(channelFactory); connectionFactory1.setRxChannelFactory(channelFactory); // creating source AudioPlayerFactory genFactory = new AudioPlayerFactory(); genFactory.setName("test-source"); // configuring sender sender = new EndpointImpl("/ivr/test/sender"); sender.setTimer(timer); sender.setConnectionFactory(connectionFactory1); sender.setSourceFactory(genFactory); sender.setRtpFactory(rtpFactories2); sender.start(); semaphore = new Semaphore(0); } @After public void tearDown() { } /** * Test of getSink method, of class Bridge. */ @Test public void testSimpleTransmission() throws Exception { // Set-up player AudioPlayer player = (AudioPlayer) sender.getComponent("test-source"); assertNotNull(player); player.addListener(new PlayerListener()); // 13sec audio URL url = IvrTest.class.getClassLoader().getResource("org/mobicents/media/server/impl/8kulaw.wav"); player.setURL(url.toExternalForm()); // set-up recorder Recorder recorder = (Recorder) ivrEnp.getComponent("RecorderFactory"); assertNotNull(recorder); String tempFilePath = url.getPath(); String recordDir = tempFilePath.substring(0, tempFilePath.lastIndexOf('/')); recorder.setRecordDir(recordDir); // let us record for 7 sec recorder.addListener(new RecorderListener()); Connection rxConnection = ivrEnp.createConnection(ConnectionMode.RECV_ONLY); Connection txConnection = sender.createConnection(ConnectionMode.SEND_ONLY); txConnection.setRemoteDescriptor(rxConnection.getLocalDescriptor()); rxConnection.setRemoteDescriptor(txConnection.getLocalDescriptor()); DtmfGenerator dtmfGene = (DtmfGenerator) txConnection.getComponent("Rfc2833GeneratorFactory", Connection.CHANNEL_TX); assertNotNull(dtmfGene); dtmfGene.setDigit("5"); DtmfDetector dtmfDete = (DtmfDetector) rxConnection.getComponent("Rfc2833DetectorFactory", Connection.CHANNEL_RX); assertNotNull(dtmfDete); dtmfDete.addListener(new DTMFListener(5)); dtmfDete.start(); player.start(); recorder.setRecordFile("ivr-test/8kulaw.wav"); recorder.start(); semaphore.tryAcquire(5, TimeUnit.SECONDS); //Fire dtmf dtmfGene.start(); //wait for another few secs semaphore.tryAcquire(8, TimeUnit.SECONDS); assertTrue(started); // assertTrue(completed); assertFalse(failed); assertFalse(end_of_media); assertFalse(stopped); assertTrue(receivedEvent); } private class RecorderListener implements NotificationListener { public void update(NotifyEvent event) { switch (event.getEventID()) { case RecorderEvent.STOPPED: stopped = true; semaphore.release(); break; case RecorderEvent.DURATION_OVER: completed = true; semaphore.release(); break; case RecorderEvent.FAILED: failed = true; semaphore.release(); break; } } } private class PlayerListener implements NotificationListener { public void update(NotifyEvent event) { switch (event.getEventID()) { case AudioPlayerEvent.STARTED: started = true; break; case NotifyEvent.COMPLETED: end_of_media = true; semaphore.release(); break; case AudioPlayerEvent.START_FAILED: failed = true; semaphore.release(); break; } } } private class DTMFListener implements NotificationListener { int eventId = 0; public DTMFListener(int eventId) { this.eventId = eventId; } public void update(NotifyEvent event) { if (event.getEventID() == eventId) { receivedEvent = true; } } } }