/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.restcomm.media.control.mgcp.endpoint;
import java.util.concurrent.Semaphore;
import org.restcomm.media.Component;
import org.restcomm.media.ComponentType;
import org.restcomm.media.component.audio.AudioComponent;
import org.restcomm.media.component.oob.OOBComponent;
import org.restcomm.media.control.mgcp.resources.ResourcesPool;
import org.restcomm.media.resource.dtmf.DetectorImpl;
import org.restcomm.media.resource.dtmf.GeneratorImpl;
import org.restcomm.media.resource.player.audio.AudioPlayerImpl;
import org.restcomm.media.resource.recorder.audio.AudioRecorderImpl;
import org.restcomm.media.spi.ConnectionMode;
import org.restcomm.media.spi.Endpoint;
/**
* Implements Local Components Holder for endpoint
* Usefull for jsr 309 structure
* @author Oifa Yulian
*/
public class MediaGroup {
private Component player;
private Component recorder;
private Component dtmfDetector;
private Component dtmfGenerator;
private ResourcesPool resourcesPool;
private AudioComponent audioComponent;
private OOBComponent oobComponent;
private Endpoint endpoint;
private int readComponents=0,writeComponents=0;
private int readDtmfComponents=0,writeDtmfComponents=0;
private Semaphore resourceSemaphore=new Semaphore(1);
public MediaGroup(ResourcesPool resourcesPool,Endpoint endpoint)
{
this.resourcesPool=resourcesPool;
this.audioComponent=new AudioComponent(0);
this.oobComponent=new OOBComponent(0);
this.endpoint=endpoint;
}
public AudioComponent getAudioComponent()
{
return this.audioComponent;
}
public OOBComponent getOOBComponent()
{
return this.oobComponent;
}
public Component getPlayer()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.player==null)
{
this.player=resourcesPool.newAudioComponent(ComponentType.PLAYER);
audioComponent.addInput(((AudioPlayerImpl)this.player).getAudioInput());
readComponents++;
audioComponent.updateMode(true,writeComponents!=0);
updateEndpoint(1,0);
}
}
finally
{
resourceSemaphore.release();
}
return this.player;
}
public void releasePlayer()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.player!=null)
{
audioComponent.remove(((AudioPlayerImpl)this.player).getAudioInput());
readComponents--;
audioComponent.updateMode(readComponents!=0,writeComponents!=0);
updateEndpoint(-1,0);
((AudioPlayerImpl)this.player).clearAllListeners();
this.player.deactivate();
resourcesPool.releaseAudioComponent(this.player,ComponentType.PLAYER);
this.player=null;
}
}
finally
{
resourceSemaphore.release();
}
}
public boolean hasPlayer()
{
return this.player!=null;
}
public Component getRecorder()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.recorder==null)
{
this.recorder=resourcesPool.newAudioComponent(ComponentType.RECORDER);
audioComponent.addOutput(((AudioRecorderImpl)this.recorder).getAudioOutput());
oobComponent.addOutput(((AudioRecorderImpl)this.recorder).getOOBOutput());
writeComponents++;
writeDtmfComponents++;
audioComponent.updateMode(readComponents!=0,true);
oobComponent.updateMode(readDtmfComponents!=0,true);
updateEndpoint(0,1);
}
}
finally
{
resourceSemaphore.release();
}
return this.recorder;
}
public void releaseRecorder()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.recorder!=null)
{
audioComponent.remove(((AudioRecorderImpl)this.recorder).getAudioOutput());
oobComponent.remove(((AudioRecorderImpl)this.recorder).getOOBOutput());
writeComponents--;
writeDtmfComponents--;
audioComponent.updateMode(readComponents!=0,writeComponents!=0);
oobComponent.updateMode(readDtmfComponents!=0,writeDtmfComponents!=0);
updateEndpoint(0,-1);
((AudioRecorderImpl)this.recorder).clearAllListeners();
this.recorder.deactivate();
resourcesPool.releaseAudioComponent(this.recorder,ComponentType.RECORDER);
this.recorder=null;
}
}
finally
{
resourceSemaphore.release();
}
}
public boolean hasRecorder()
{
return this.recorder!=null;
}
public Component getDtmfDetector()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.dtmfDetector==null)
{
this.dtmfDetector=resourcesPool.newAudioComponent(ComponentType.DTMF_DETECTOR);
audioComponent.addOutput(((DetectorImpl)this.dtmfDetector).getAudioOutput());
oobComponent.addOutput(((DetectorImpl)this.dtmfDetector).getOOBOutput());
writeComponents++;
writeDtmfComponents++;
audioComponent.updateMode(readComponents!=0,true);
oobComponent.updateMode(readDtmfComponents!=0,true);
updateEndpoint(0,1);
}
}
finally
{
resourceSemaphore.release();
}
return this.dtmfDetector;
}
public void releaseDtmfDetector()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.dtmfDetector!=null)
{
audioComponent.remove(((DetectorImpl)this.dtmfDetector).getAudioOutput());
oobComponent.remove(((DetectorImpl)this.dtmfDetector).getOOBOutput());
writeComponents--;
writeDtmfComponents--;
audioComponent.updateMode(readComponents!=0,writeComponents!=0);
oobComponent.updateMode(readDtmfComponents!=0,writeDtmfComponents!=0);
updateEndpoint(0,-1);
((DetectorImpl)this.dtmfDetector).clearAllListeners();
this.dtmfDetector.deactivate();
((DetectorImpl)this.dtmfDetector).clearBuffer();
resourcesPool.releaseAudioComponent(this.dtmfDetector,ComponentType.DTMF_DETECTOR);
this.dtmfDetector=null;
}
}
finally
{
resourceSemaphore.release();
}
}
public boolean hasDtmfDetector()
{
return this.dtmfDetector!=null;
}
public Component getDtmfGenerator()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.dtmfGenerator==null)
{
this.dtmfGenerator=resourcesPool.newAudioComponent(ComponentType.DTMF_GENERATOR);
audioComponent.addInput(((GeneratorImpl)this.dtmfGenerator).getAudioInput());
oobComponent.addInput(((GeneratorImpl)this.dtmfGenerator).getOOBInput());
readComponents++;
readDtmfComponents++;
audioComponent.updateMode(true,writeComponents!=0);
oobComponent.updateMode(true,writeDtmfComponents!=0);
updateEndpoint(1,0);
}
}
finally
{
resourceSemaphore.release();
}
return this.dtmfGenerator;
}
public void releaseDtmfGenerator()
{
try
{
resourceSemaphore.acquire();
}
catch(Exception ex)
{
}
try
{
if(this.dtmfGenerator!=null)
{
audioComponent.remove(((GeneratorImpl)this.dtmfGenerator).getAudioInput());
oobComponent.remove(((GeneratorImpl)this.dtmfGenerator).getOOBInput());
readComponents--;
readDtmfComponents--;
audioComponent.updateMode(readComponents!=0,writeComponents!=0);
oobComponent.updateMode(readDtmfComponents!=0,writeDtmfComponents!=0);
updateEndpoint(-1,0);
this.dtmfGenerator.deactivate();
resourcesPool.releaseAudioComponent(this.dtmfGenerator,ComponentType.DTMF_GENERATOR);
this.dtmfGenerator=null;
}
}
finally
{
resourceSemaphore.release();
}
}
public boolean hasDtmfGenerator()
{
return this.dtmfGenerator!=null;
}
private void updateEndpoint(int readChange,int writeChange)
{
boolean oldRead=(readComponents-readChange)!=0;
boolean oldWrite=(writeComponents-writeChange)!=0;
boolean newRead=readComponents!=0;
boolean newWrite=writeComponents!=0;
if(newRead==oldRead && newWrite==oldWrite)
return;
ConnectionMode oldMode,newMode;
if(oldRead)
{
if(oldWrite)
oldMode=ConnectionMode.CONFERENCE;
else
oldMode=ConnectionMode.RECV_ONLY;
}
else if(oldWrite)
oldMode=ConnectionMode.SEND_ONLY;
else
oldMode=ConnectionMode.INACTIVE;
if(newRead)
{
if(newWrite)
newMode=ConnectionMode.CONFERENCE;
else
newMode=ConnectionMode.RECV_ONLY;
}
else if(newWrite)
newMode=ConnectionMode.SEND_ONLY;
else
newMode=ConnectionMode.INACTIVE;
endpoint.modeUpdated(oldMode,newMode);
}
public void releaseAll()
{
releasePlayer();
releaseRecorder();
releaseDtmfDetector();
releaseDtmfGenerator();
}
}