Copy audio notify service and activate it through neomedia.

cusax-fix
Damian Minkov 16 years ago
parent b518e93f84
commit 6f62b3b802

@ -1062,6 +1062,8 @@
prefix="net/java/sip/communicator/impl/media/protocol"/>
<zipfileset dir="${dest}/net/java/sip/communicator/impl/media/renderer"
prefix="net/java/sip/communicator/impl/media/renderer"/>
<zipfileset dir="${dest}/net/java/sip/communicator/service/audionotifier"
prefix="net/java/sip/communicator/service/audionotifier"/>
<zipfileset dir="${resources}/images/impl/media"
prefix="resources/images/impl/media"/>
<zipfileset src="${lib.win.noinst}/jmf.jar" prefix=""/>
@ -1095,6 +1097,8 @@
prefix="net/java/sip/communicator/impl/media/protocol"/>
<zipfileset dir="${dest}/net/java/sip/communicator/impl/media/renderer"
prefix="net/java/sip/communicator/impl/media/renderer"/>
<zipfileset dir="${dest}/net/java/sip/communicator/service/audionotifier"
prefix="net/java/sip/communicator/service/audionotifier"/>
<zipfileset dir="${resources}/images/impl/media"
prefix="resources/images/impl/media"/>
<zipfileset src="${lib.lin.noinst}/jmf.jar" prefix=""/>
@ -1127,6 +1131,8 @@
prefix="net/java/sip/communicator/impl/media/protocol"/>
<zipfileset dir="${dest}/net/java/sip/communicator/impl/media/renderer"
prefix="net/java/sip/communicator/impl/media/renderer"/>
<zipfileset dir="${dest}/net/java/sip/communicator/service/audionotifier"
prefix="net/java/sip/communicator/service/audionotifier"/>
<zipfileset dir="${resources}/images/impl/media"
prefix="resources/images/impl/media"/>
<zipfileset src="${lib.mac.noinst}/jmf.jar" prefix=""/>

@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.neomedia;
import net.java.sip.communicator.service.audionotifier.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.fileaccess.*;
import net.java.sip.communicator.service.gui.*;
@ -14,6 +15,8 @@
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.impl.neomedia.notify.*;
import org.osgi.framework.*;
/**
@ -122,6 +125,24 @@ public void start(BundleContext bundleContext)
//following property to make sure that it would accept java generated
//IPv6 addresses that contain address scope zones.
System.setProperty("gov.nist.core.STRIP_ADDR_SCOPES", "true");
// AudioNotify Service
AudioNotifierServiceImpl audioNotifier = new AudioNotifierServiceImpl(
mediaServiceImpl.getDeviceConfiguration());
audioNotifier.setMute(
!getConfigurationService()
.getBoolean(
"net.java.sip.communicator.impl.sound.isSoundEnabled",
true));
getBundleContext()
.registerService(
AudioNotifierService.class.getName(),
audioNotifier,
null);
logger.info("Audio Notifier Service ...[REGISTERED]");
}
/**

@ -38,6 +38,7 @@ Import-Package: org.osgi.framework,
gnu.java.zrtp.utils,
gnu.java.zrtp.zidfile
Export-Package: net.java.sip.communicator.service.neomedia,
net.java.sip.communicator.service.audionotifier,
net.java.sip.communicator.service.neomedia.device,
net.java.sip.communicator.service.neomedia.event,
net.java.sip.communicator.service.neomedia.format

@ -0,0 +1,175 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.neomedia.notify;
import java.net.*;
import java.util.*;
import net.java.sip.communicator.impl.neomedia.*;
import net.java.sip.communicator.impl.neomedia.device.*;
import net.java.sip.communicator.service.audionotifier.*;
import net.java.sip.communicator.util.*;
/**
* The implementation of the AudioNotifierService.
*
* @author Yana Stamcheva
*/
public class AudioNotifierServiceImpl
implements AudioNotifierService,
PropertyChangeListener
{
private static final Map<String, SCAudioClipImpl> audioClips =
new HashMap<String, SCAudioClipImpl>();
private boolean isMute;
/**
* Device config to look for notify device.
*/
private DeviceConfiguration deviceConfiguration;
/**
* Creates audio notify service.
* @param deviceConfiguration the device configuration.
*/
public AudioNotifierServiceImpl(DeviceConfiguration deviceConfiguration)
{
this.deviceConfiguration = deviceConfiguration;
deviceConfiguration.addPropertyChangeListener(this);
}
/**
* Creates an SCAudioClip from the given URI and adds it to the list of
* available audio-s.
*
* @param uri the path where the audio file could be found
*/
public SCAudioClipImpl createAudio(String uri)
{
SCAudioClipImpl audioClip;
synchronized (audioClips)
{
if(audioClips.containsKey(uri))
{
audioClip = audioClips.get(uri);
}
else
{
URL url =
NeomediaActivator.getResources().getSoundURLForPath(uri);
if (url == null)
{
// Not found by the class loader. Perhaps it's a local file.
try
{
url = new URL(uri);
}
catch (MalformedURLException e)
{
//logger.error("The given uri could not be parsed.", e);
return null;
}
}
try
{
if(getDeviceConfiguration().getAudioSystem().equals(
DeviceConfiguration.AUDIO_SYSTEM_JAVASOUND))
{
audioClip = new JMFAudioClipImpl(url, this);
}
else if(getDeviceConfiguration().getAudioSystem().equals(
DeviceConfiguration.AUDIO_SYSTEM_PORTAUDIO))
{
audioClip = new PortAudioClipImpl(url, this);
}
else
return null;
}
catch (Throwable e)
{
// Cannot create audio to play
return null;
}
audioClips.put(uri, audioClip);
}
}
return audioClip;
}
/**
* Removes the given audio from the list of available audio clips.
*
* @param audioClip the audio to destroy
*/
public void destroyAudio(SCAudioClip audioClip)
{
synchronized (audioClips) {
audioClips.remove(audioClip);
}
}
/**
* Enables or disables the sound in the application. If FALSE, we try to
* restore all looping sounds if any.
*
* @param isMute when TRUE disables the sound, otherwise enables the sound.
*/
public void setMute(boolean isMute)
{
this.isMute = isMute;
for (SCAudioClipImpl audioClip : audioClips.values())
{
if (isMute)
{
audioClip.internalStop();
}
else if (audioClip.isLooping())
{
audioClip.playInLoop(audioClip.getLoopInterval());
}
}
}
/**
* Returns TRUE if the sound is currently disabled, FALSE otherwise.
* @return TRUE if the sound is currently disabled, FALSE otherwise
*/
public boolean isMute()
{
return isMute;
}
/**
* The device configuration.
*
* @return the deviceConfiguration
*/
public DeviceConfiguration getDeviceConfiguration()
{
return deviceConfiguration;
}
/**
* Listens for changes in notify device
* @param evt the event that notify device has changed.
*/
public void propertyChange(PropertyChangeEvent evt)
{
if(evt.getPropertyName().equals(
DeviceConfiguration.AUDIO_NOTIFY_DEVICE))
{
audioClips.clear();
}
}
}

@ -0,0 +1,201 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.neomedia.notify;
import java.applet.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.security.*;
import javax.swing.*;
import net.java.sip.communicator.service.audionotifier.*;
/**
* Implementation of SCAudioClip.
*
* @author Yana Stamcheva
*/
public class JMFAudioClipImpl
extends SCAudioClipImpl
implements ActionListener
{
private static Constructor<AudioClip> acConstructor = null;
private final Timer playAudioTimer = new Timer(1000, null);
private final AudioClip audioClip;
private final AudioNotifierService audioNotifier;
/**
* Creates the audio clip and initialize the listener used from the
* loop timer.
*
* @param url the url pointing to the audio file
* @param audioNotifier the audio notify service
* @throws IOException cannot audio clip with supplied url.
*/
public JMFAudioClipImpl(URL url, AudioNotifierService audioNotifier)
throws IOException
{
this.audioClip = createAppletAudioClip(url.openStream());
this.audioNotifier = audioNotifier;
this.playAudioTimer.addActionListener(this);
}
/**
* Plays this audio.
*/
public void play()
{
if ((audioClip != null) && !audioNotifier.isMute())
audioClip.play();
}
/**
* Plays this audio in loop.
*
* @param interval the loop interval
*/
public void playInLoop(int interval)
{
if(!audioNotifier.isMute())
{
if(interval == 0)
audioClip.loop();
else
{
//first play the audio and then start the timer and wait
audioClip.play();
playAudioTimer.setDelay(interval);
playAudioTimer.setRepeats(true);
playAudioTimer.start();
}
}
setLoopInterval(interval);
setIsLooping(true);
}
/**
* Stops this audio.
*/
public void stop()
{
if (audioClip != null)
audioClip.stop();
if (isLooping())
{
playAudioTimer.stop();
setIsLooping(false);
}
}
/**
* Stops this audio without setting the isLooping property in the case of
* a looping audio. The AudioNotifier uses this method to stop the audio
* when setMute(true) is invoked. This allows us to restore all looping
* audios when the sound is restored by calling setMute(false).
*/
public void internalStop()
{
if (audioClip != null)
audioClip.stop();
if (isLooping())
playAudioTimer.stop();
}
/**
* Creates an AppletAudioClip.
*
* @param inputstream the audio input stream
* @throws IOException
*/
private static AudioClip createAppletAudioClip(InputStream inputstream)
throws IOException
{
if (acConstructor == null)
{
try
{
acConstructor
= AccessController.doPrivileged(
new PrivilegedExceptionAction<Constructor<AudioClip>>()
{
public Constructor<AudioClip> run()
throws ClassNotFoundException,
NoSuchMethodException,
SecurityException
{
return createAcConstructor();
}
});
}
catch (PrivilegedActionException paex)
{
throw
new IOException(
"Failed to get AudioClip constructor: "
+ paex.getException());
}
}
try
{
return acConstructor.newInstance(inputstream);
}
catch (Exception ex)
{
throw new IOException("Failed to construct the AudioClip: " + ex);
}
}
@SuppressWarnings("unchecked")
private static Constructor<AudioClip> createAcConstructor()
throws ClassNotFoundException,
NoSuchMethodException,
SecurityException
{
Class<?> class1;
try
{
class1
= Class.forName(
"com.sun.media.sound.JavaSoundAudioClip",
true,
ClassLoader.getSystemClassLoader());
}
catch (ClassNotFoundException cnfex)
{
class1
= Class.forName("sun.audio.SunAudioClip", true, null);
}
return
(Constructor<AudioClip>) class1.getConstructor(InputStream.class);
}
/**
* Plays an audio clip. Used in the playAudioTimer to play an audio in loop.
* @param e the event.
*/
public void actionPerformed(ActionEvent e)
{
if (audioClip != null)
{
audioClip.stop();
audioClip.play();
}
}
}

@ -0,0 +1,170 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.neomedia.notify;
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;
import net.java.sip.communicator.impl.media.protocol.portaudio.*;
import net.java.sip.communicator.impl.media.protocol.portaudio.streams.*;
import net.java.sip.communicator.util.*;
/**
* Implementation of SCAudioClip using PortAudio.
*
* @author Damian Minkov
*/
public class PortAudioClipImpl
extends SCAudioClipImpl
{
private static final Logger logger
= Logger.getLogger(PortAudioClipImpl.class);
private final AudioNotifierServiceImpl audioNotifier;
private boolean started = false;
private final URL url;
/**
* Creates the audio clip and initialize the listener used from the
* loop timer.
*
* @param url the url pointing to the audio file
* @param audioNotifier the audio notify service
* @throws IOException cannot audio clip with supplied url.
*/
public PortAudioClipImpl(URL url, AudioNotifierServiceImpl audioNotifier)
throws IOException
{
this.audioNotifier = audioNotifier;
this.url = url;
}
/**
* Plays this audio.
*/
public void play()
{
if ((url != null) && !audioNotifier.isMute())
{
started = true;
new Thread(new PlayThread()).start();
}
}
/**
* Plays this audio in loop.
*
* @param interval the loop interval
*/
public void playInLoop(int interval)
{
setLoopInterval(interval);
setIsLooping(true);
play();
}
/**
* Stops this audio.
*/
public void stop()
{
internalStop();
setIsLooping(false);
}
/**
* Stops this audio without setting the isLooping property in the case of
* a looping audio. The AudioNotifier uses this method to stop the audio
* when setMute(true) is invoked. This allows us to restore all looping
* audios when the sound is restored by calling setMute(false).
*/
public void internalStop()
{
if (url != null)
started = false;
}
private class PlayThread
implements Runnable
{
byte[] buffer = new byte[1024];
private OutputPortAudioStream portAudioStream = null;
public void run()
{
try
{
while(true)
{
AudioInputStream audioStream =
AudioSystem.getAudioInputStream(url);
AudioFormat audioStreamFormat = audioStream.getFormat();
if (portAudioStream == null)
{
int deviceIndex =
PortAudioUtils.getDeviceIndexFromLocator(
audioNotifier.getDeviceConfiguration().
getAudioNotifyDevice().getLocator());
portAudioStream = PortAudioManager.getInstance().
getOutputStream(
deviceIndex,
audioStreamFormat.getSampleRate(),
audioStreamFormat.getChannels(),
PortAudioUtils.getPortAudioSampleFormat(
audioStreamFormat.getSampleSizeInBits()));
portAudioStream.start();
}
if(!started)
{
portAudioStream.stop();
return;
}
while(audioStream.read(buffer) != -1)
{
portAudioStream.write(buffer);
}
if(!isLooping())
{
portAudioStream.stop();
break;
}
else
{
Thread.sleep(getLoopInterval());
}
}
}
catch (PortAudioException e)
{
logger.error(
"Cannot open portaudio device for notifications", e);
}
catch (IOException e)
{
logger.error("Error reading from audio resource", e);
}
catch (InterruptedException e)
{
logger.error("Cannot wait the interval between plays", e);
}
catch (UnsupportedAudioFileException e)
{
logger.error("Unknown file format", e);
}
}
}
}

@ -0,0 +1,94 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.neomedia.notify;
import net.java.sip.communicator.service.audionotifier.*;
/**
* Common properties impl for SCAudioClip.
*
* @author Damian Minkov
*/
public abstract class SCAudioClipImpl
implements SCAudioClip
{
private boolean isLooping;
private int loopInterval;
private boolean isInvalid;
/**
* Returns TRUE if this audio is invalid, FALSE otherwise.
*
* @return TRUE if this audio is invalid, FALSE otherwise
*/
public boolean isInvalid()
{
return isInvalid;
}
/**
* Marks this audio as invalid or not.
*
* @param isInvalid TRUE to mark this audio as invalid, FALSE otherwise
*/
public void setInvalid(boolean isInvalid)
{
this.setIsInvalid(isInvalid);
}
/**
* Returns TRUE if this audio is currently playing in loop, FALSE otherwise.
* @return TRUE if this audio is currently playing in loop, FALSE otherwise.
*/
public boolean isLooping()
{
return isLooping;
}
/**
* Returns the loop interval if this audio is looping.
* @return the loop interval if this audio is looping
*/
public int getLoopInterval()
{
return loopInterval;
}
/**
* @param isLooping the isLooping to set
*/
public void setIsLooping(boolean isLooping)
{
this.isLooping = isLooping;
}
/**
* @param loopInterval the loopInterval to set
*/
public void setLoopInterval(int loopInterval)
{
this.loopInterval = loopInterval;
}
/**
* @param isInvalid the isInvalid to set
*/
public void setIsInvalid(boolean isInvalid)
{
this.isInvalid = isInvalid;
}
/**
* Stops this audio without setting the isLooping property in the case of
* a looping audio. The AudioNotifier uses this method to stop the audio
* when setMute(true) is invoked. This allows us to restore all looping
* audios when the sound is restored by calling setMute(false).
*/
public abstract void internalStop();
}
Loading…
Cancel
Save