package net.sourceforge.gjtapi.raw.javasound; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.URI; import java.net.URLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Dictionary; import java.util.Properties; import javax.sound.sampled.Mixer; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Mixer.Info; import javax.telephony.ProviderUnavailableException; import javax.telephony.ResourceUnavailableException; import javax.telephony.InvalidArgumentException; import javax.telephony.MethodNotSupportedException; import javax.telephony.PrivilegeViolationException; import javax.telephony.InvalidPartyException; import javax.telephony.media.RTC; import javax.telephony.media.MediaResourceException; import javax.telephony.media.Symbol; import javax.telephony.media.PlayerConstants; import javax.telephony.media.RecorderConstants; import net.sourceforge.gjtapi.TermData; import net.sourceforge.gjtapi.CallId; import net.sourceforge.gjtapi.TelephonyListener; import net.sourceforge.gjtapi.raw.MediaTpi; import net.sourceforge.gjtapi.RawStateException; import net.sourceforge.gjtapi.RawSigDetectEvent; import net.sourceforge.gjtapi.raw.javasound.desktopAgent.DesktopAgent; import net.sourceforge.gjtapi.raw.javasound.desktopAgent.DesktopAgentProps; import java.util.concurrent.Semaphore; import java.io.InputStream; import java.io.OutputStream; /** * <p>Title: JavaSoundProvider</p> * * <p>Description: This is a provider that provides the Audio System support * for GJTAPI</p> * * <p>Copyright: Copyright (c) 2008</p> * * <p>Company: INESC-ID</p> * * @author D�rio Marcelino * @version 1.0 */ public class JavaSoundProvider implements MediaTpi { private TelephonyListener listener; protected HashMap<String, DesktopAgent> desktopAgents = new HashMap<String, DesktopAgent>(); protected Semaphore playSemaphore; protected Semaphore recSemaphore; public JavaSoundProvider() { playSemaphore = new Semaphore(1, true); recSemaphore = new Semaphore(1, true); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void initialize(Map props) throws ProviderUnavailableException { HashMap<String, Mixer> playbackMixers = new HashMap<String, Mixer>(); HashMap<String, Mixer> captureMixers = new HashMap<String, Mixer>(); //Get audio resources Info infoMixers[] = AudioSystem.getMixerInfo(); for (Info mixerInfo : infoMixers) { if (mixerInfo.getDescription().toLowerCase().contains("playback") && !mixerInfo.getDescription().toLowerCase().contains("capture")) { playbackMixers.put(mixerInfo.getName(), AudioSystem.getMixer(mixerInfo)); } else if (mixerInfo.getDescription().toLowerCase().contains( "capture") && !mixerInfo.getDescription().toLowerCase().contains( "playback")) { captureMixers.put(mixerInfo.getName(), AudioSystem.getMixer(mixerInfo)); } else { playbackMixers.put(mixerInfo.getName(), AudioSystem.getMixer(mixerInfo)); captureMixers.put(mixerInfo.getName(), AudioSystem.getMixer(mixerInfo)); } } //Get Agents for (Object property : props.keySet()) { //System.out.println((String)property); if (!((String) property).contains("gjtapi.javasound.desktopAgent.")) { continue; } String propParts[] = ((String) property).split("[.]"); if (propParts[3].compareToIgnoreCase("default") != 0 && ((String) props.get("gjtapi.javasound.desktopAgent." + propParts[3] + ".enabled")).compareToIgnoreCase("true") == 0) { desktopAgents.put(propParts[3], null); } } //Instanciate the agents for (String ad : desktopAgents.keySet()) { //System.out.println(ad); DesktopAgentProps agentProperties = new DesktopAgentProps(ad, props); DesktopAgent desktopAgent = new DesktopAgent(agentProperties, playbackMixers, captureMixers, this); desktopAgents.put(ad, desktopAgent); } } /** * {@inheritDoc} */ public Properties getCapabilities() { return null; } /** * {@inheritDoc} */ public String[] getAddresses() throws ResourceUnavailableException { String[] ret = new String[desktopAgents.size()]; int i = 0; for (String addresses : desktopAgents.keySet()) { ret[i] = addresses; i++; } return ret; } /** * {@inheritDoc} */ public String[] getAddresses(String terminal) throws InvalidArgumentException { DesktopAgent desktopAgent = desktopAgents.get(terminal); if (desktopAgent == null) { return new String[] {}; } else { return new String[] {terminal}; } } /** * {@inheritDoc} */ public TermData[] getTerminals() throws ResourceUnavailableException { TermData[] ret = new TermData[desktopAgents.size()]; int i = 0; for (String address : desktopAgents.keySet()) { ret[i] = new TermData(address, true); i++; } return ret; } /** * {@inheritDoc} */ public TermData[] getTerminals(String address) throws InvalidArgumentException { DesktopAgent da = desktopAgents.get(address); if (da == null) { return new TermData[] {}; } else { return new TermData[] { new TermData(address, true) }; } } /** * {@inheritDoc} */ public void releaseCallId(CallId id) { } /** * {@inheritDoc} */ public void addListener(TelephonyListener ro) { if (listener == null) { listener = ro; } else { System.err.println("Request to add a TelephonyListener to " + this.getClass().getName() + ", but one is already registered"); } } /** * {@inheritDoc} */ public void removeListener(TelephonyListener ro) { if (ro == listener) { listener = null; } else { System.err.println("Request to remove a TelephonyListener from " + this.getClass().getName() + ", but it wasn't registered"); } } /** * {@inheritDoc} */ public void shutdown() { /* for (DesktopAgent ad : desktopAgents.values()) { ad.hangup(); }*/ desktopAgents.clear(); } // ******************* Basic Call Control ****************** /** * {@inheritDoc} */ public void answerCall(CallId call, String address, String terminal) throws PrivilegeViolationException, ResourceUnavailableException, MethodNotSupportedException, RawStateException { //Get AD DesktopAgent ad = desktopAgents.get(address); if (ad == null) { throw new ResourceUnavailableException(ResourceUnavailableException. ORIGINATOR_UNAVAILABLE, "Address not found: " + address); } if (ad.getJavaSoundCallId().equals((Object) call)) { ad.accept(); } else { throw new ResourceUnavailableException(ResourceUnavailableException. UNSPECIFIED_LIMIT_EXCEEDED); } } /** * {@inheritDoc} */ public CallId reserveCallId(String address) throws InvalidArgumentException { JavaSoundCallId id = new JavaSoundCallId(); return id; } /** * {@inheritDoc} */ public CallId createCall(CallId id, String address, String term, String dest) throws ResourceUnavailableException, PrivilegeViolationException, InvalidPartyException, InvalidArgumentException, RawStateException, MethodNotSupportedException { DesktopAgent ad = desktopAgents.get(address); if (ad == null) { throw new ResourceUnavailableException(ResourceUnavailableException. ORIGINATOR_UNAVAILABLE, "Address not found: " + address); } ad.call((JavaSoundCallId) id, dest); return id; } /** * {@inheritDoc} */ public void release(String address, CallId call) throws PrivilegeViolationException, ResourceUnavailableException, MethodNotSupportedException, RawStateException { DesktopAgent ad = desktopAgents.get(address); if (ad == null) { throw new ResourceUnavailableException(ResourceUnavailableException. ORIGINATOR_UNAVAILABLE, "Address not found: " + address); } ad.hangup(); } // ******************* TelephonyListener ****************** /** * {@inheritDoc} */ public void callActive(CallId id, int cause) { listener.callActive(id, cause); } /** * {@inheritDoc} */ public void connectionInProgress(CallId id, String address, int cause) { listener.connectionInProgress(id, address, cause); } /** * {@inheritDoc} */ public void connectionAlerting(CallId id, String address, int cause) { listener.connectionAlerting(id, address, cause); } /** * {@inheritDoc} */ public void connectionConnected(CallId id, String address, int cause) { listener.connectionConnected(id, address, cause); } /** * {@inheritDoc} */ public void connectionDisconnected(CallId id, String address, int cause) { if (listener != null) { listener.connectionDisconnected(id, address, cause); } } /** * {@inheritDoc} */ public void terminalConnectionCreated(CallId id, String address, String terminal, int cause) { listener.terminalConnectionCreated(id, address, terminal, cause); } /** * {@inheritDoc} */ public void terminalConnectionRinging(CallId id, String address, String terminal, int cause) { listener.terminalConnectionRinging(id, address, terminal, cause); } // *************************** Media ************************* /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public boolean allocateMedia(String terminal, int type, Dictionary resourceArgs) { return true; } /** * {@inheritDoc} */ public boolean freeMedia(String terminal, int type) { //Get desktopAgent DesktopAgent da = desktopAgents.get(terminal); if (da == null) { return false; } da.stop(); return true; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void play(String terminal, String[] streamIds, int offset, RTC[] rtcs, Dictionary optArgs) throws MediaResourceException { int dur = javax.telephony.media.ResourceConstants.v_Forever; try { //System.out.println("GJTAPI Play, starting"); do { try { playSemaphore.acquire(1); break; } catch (InterruptedException ex) { ex.printStackTrace(); } } while (true); //System.out.println("GJTAPI Play, acquired semaphore"); //Get desktopAgent DesktopAgent da = desktopAgents.get(terminal); if (da == null) { throw new MediaResourceException("Terminal not found: " + terminal); } //Process RTC if (rtcs != null) { for (RTC rtc : rtcs) { if (rtc.getTrigger() == PlayerConstants.p_MaxDuration) { dur = rtc.getAction().hashCode(); } } } for (String streamID : streamIds) { URI uri = new URI(streamID); if (uri.getScheme().equals("file")) { FileInputStream fis = new FileInputStream(uri.getPath()); da.play(fis, dur); } else { URL url = new URL(streamID); URLConnection c = url.openConnection(); c.connect(); InputStream is = c.getInputStream(); da.play(is, dur); is.close(); } } } catch (IllegalMonitorStateException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); throw new MediaResourceException(); } //System.out.println("GJTAPI Play, finished"); playSemaphore.release(1); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void record(String terminal, String streamId, RTC[] rtcs, Dictionary optArgs) throws MediaResourceException { int dur = javax.telephony.media.ResourceConstants.v_Forever; //System.out.println("GJTAPI Record, starting"); do { try { recSemaphore.acquire(1); break; } catch (InterruptedException ex) { ex.printStackTrace(); } } while (true); //System.out.println("GJTAPI Record, acquired semaphore"); //Get desktopAgent DesktopAgent da = desktopAgents.get(terminal); if (da == null) { throw new MediaResourceException("Terminal not found: " + terminal); } //Process RTC if (rtcs != null) { for (RTC rtc : rtcs) { if (rtc.getTrigger() == RecorderConstants.p_MaxDuration) { dur = rtc.getAction().hashCode(); } } } try { URI uri = new URI(streamId); if (uri.getScheme().equals("file")) { FileOutputStream fos = new FileOutputStream(uri.getPath()); da.record(fos, dur); } else { URL url = new URL(streamId); URLConnection c = url.openConnection(); c.connect(); OutputStream os = c.getOutputStream(); da.record(os, dur); os.close(); } } catch (Exception e) { e.printStackTrace(); throw new MediaResourceException(); } //System.out.println("GJTAPI Record, finished"); recSemaphore.release(1); } /** * {@inheritDoc} */ public void stop(String terminal) { //Get desktopAgent DesktopAgent da = desktopAgents.get(terminal); if (da == null) { return; } da.stop(); } /** * {@inheritDoc} */ public void triggerRTC(String terminal, Symbol action) { //Get desktopAgent DesktopAgent da = desktopAgents.get(terminal); if (da == null) { return; } if (action.equals(PlayerConstants.rtca_Stop)) { da.stopPlay(); } else if (action.equals(RecorderConstants.rtca_Stop)) { da.stopRecord(); } } /** * {@inheritDoc} */ public boolean isMediaTerminal(String terminal) { return true; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public RawSigDetectEvent retrieveSignals(String terminal, int num, Symbol[] patterns, RTC[] rtcs, Dictionary optArgs) throws MediaResourceException { // TODO Auto-generated method stub return null; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void sendSignals(String terminal, Symbol[] syms, RTC[] rtcs, Dictionary optArgs) throws MediaResourceException { // TODO Auto-generated method stub } /** * removeDesktopAgent * * @param address String */ public void removeDesktopAgent(String address) { desktopAgents.remove(address); //System.out.println(address + " shutdown"); } }