diff --git a/src/net/java/sip/communicator/impl/gui/GuiActivator.java b/src/net/java/sip/communicator/impl/gui/GuiActivator.java index 0ef5a5346..fcf1d9e3e 100644 --- a/src/net/java/sip/communicator/impl/gui/GuiActivator.java +++ b/src/net/java/sip/communicator/impl/gui/GuiActivator.java @@ -19,6 +19,7 @@ import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.keybindings.*; import net.java.sip.communicator.service.metahistory.*; +import net.java.sip.communicator.service.neomedia.*; import net.java.sip.communicator.service.notification.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.resources.*; @@ -66,6 +67,8 @@ public class GuiActivator implements BundleActivator private static DesktopService desktopService; + private static MediaService mediaService; + private static final Map providerFactoriesMap = new Hashtable(); @@ -453,6 +456,25 @@ public static DesktopService getDesktopService() return desktopService; } + /** + * Returns the MediaService obtained from the bundle context. + * + * @return the MediaService obtained from the bundle context + */ + public static MediaService getMediaService() + { + if (mediaService == null) + { + ServiceReference serviceReference = bundleContext + .getServiceReference(MediaService.class.getName()); + + mediaService = (MediaService) bundleContext + .getService(serviceReference); + } + + return mediaService; + } + /** * Implements the ServiceListener. Verifies whether the * passed event concerns a NotificationService and if so diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java index 3c1c0e7fa..a2dc26c0a 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java @@ -11,8 +11,8 @@ import javax.swing.*; +import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.call.*; -import net.java.sip.communicator.impl.gui.main.call.CallPeerAdapter; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.swing.*; @@ -129,7 +129,8 @@ private void addLocalCallPeer() .getOperationSet(OperationSetBasicTelephony.class); if (telephonyOpSet != null) - telephonyOpSet.addLocalUserSoundLevelListener(localPeerPanel); + GuiActivator.getMediaService(). + addLocalUserSoundLevelListener(localPeerPanel); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java index 57fca07f4..ca955c3a8 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java @@ -18,6 +18,7 @@ import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.neomedia.event.*; import net.java.sip.communicator.util.swing.*; /** diff --git a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf index c605ca02d..eb2786248 100644 --- a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf +++ b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf @@ -23,6 +23,8 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.keybindings, net.java.sip.communicator.service.metahistory, net.java.sip.communicator.service.msghistory, + net.java.sip.communicator.service.neomedia, + net.java.sip.communicator.service.neomedia.event, net.java.sip.communicator.service.notification, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.event, diff --git a/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java index 76a7084f6..7dee0a90e 100644 --- a/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java @@ -109,6 +109,20 @@ public void addSoundLevelListener(SoundLevelListener listener) // TODO Auto-generated method stub } + /** + * Adds listener to the list of SoundLevelListeners + * registered to receive notifications for changes in the levels of + * conference participants that the remote party could be mixing. + * + * @param listener the SoundLevelListener that we'd like to + * register. + */ + public void addConferenceMemberSoundLevelListener( + SoundLevelListener listener) + { + + } + /** * Registers {@link #CUSTOM_CODEC_FORMATS} with a specific * RTPManager. @@ -180,6 +194,19 @@ public void removeSoundLevelListener(SoundLevelListener listener) // TODO Auto-generated method stub } + /** + * Removes listener from the list of SoundLevelListeners + * registered to receive notification events upon changes of the sound + * level. + * + * @param listener the listener that we'd like to unregister. + */ + public void removeConferenceMemberSoundLevelListener( + SoundLevelListener listener) + { + + } + /** * Starts sending the specified DTMFTone until the * stopSendingDTMF() method is called. Callers should keep in mind diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java index 3fc11dde0..59c0fb25d 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java @@ -15,6 +15,7 @@ import net.java.sip.communicator.impl.neomedia.format.*; import net.java.sip.communicator.service.neomedia.*; import net.java.sip.communicator.service.neomedia.device.*; +import net.java.sip.communicator.service.neomedia.event.*; import net.java.sip.communicator.service.neomedia.format.*; /** @@ -91,6 +92,12 @@ public class MediaServiceImpl private final List videoDevices = new ArrayList(); + /** + * A list of listeners registered for local user sound level events. + */ + private final List soundLevelListeners + = new Vector(); + /** * Creates a new MediaStream instance which will use the specified * MediaDevice for both capture and playback of media exchanged @@ -428,4 +435,66 @@ void start() void stop() { } + + /** + * Adds the given LocalUserSoundLevelListener to this operation set. + * @param l the LocalUserSoundLevelListener to add + */ + public void addLocalUserSoundLevelListener(LocalUserSoundLevelListener l) + { + synchronized(soundLevelListeners) + { + if (!soundLevelListeners.contains(l)) + soundLevelListeners.add(l); + } + } + + /** + * Removes the given LocalUserSoundLevelListener from this + * operation set. + * @param l the LocalUserSoundLevelListener to remove + */ + public void removeLocalUserSoundLevelListener(LocalUserSoundLevelListener l) + { + synchronized(soundLevelListeners) + { + soundLevelListeners.remove(l); + } + } + + /** + * Creates and dispatches a LocalUserSoundLevelEvent notifying + * registered listeners that the local user sound level has changed. + * + * @param level the new level + */ + public void fireLocalUserSoundLevelEvent(int level) + { + LocalUserSoundLevelEvent soundLevelEvent + = new LocalUserSoundLevelEvent(this, level); + List listeners; + + synchronized (soundLevelListeners) + { + listeners = + new ArrayList(soundLevelListeners); + } + + for (Iterator listenerIter + = listeners.iterator(); listenerIter.hasNext();) + { + LocalUserSoundLevelListener listener = listenerIter.next(); + + listener.localUserSoundLevelChanged(soundLevelEvent); + } + } + + /** + * All the local sound level listeners. + * @return the soundLevelListeners interested in local sound level changes. + */ + public List getLocalSoundLevelListeners() + { + return soundLevelListeners; + } } diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/audio/SoundLevelIndicatorEffect.java b/src/net/java/sip/communicator/impl/neomedia/codec/audio/SoundLevelIndicatorEffect.java new file mode 100644 index 000000000..af7acfb40 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/codec/audio/SoundLevelIndicatorEffect.java @@ -0,0 +1,282 @@ +/* + * 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.codec.audio; + +import javax.media.*; +import javax.media.format.*; + +/** + * An effect that calculates the power of the signal and fire an event + * with the current level. + * + * @author Damian Minkov + */ +public class SoundLevelIndicatorEffect + implements Effect +{ + private Format[] supportedAudioFormats; + + /** + * Input Format + */ + private AudioFormat inputFormat; + + /** + * Output Format + */ + private AudioFormat outputFormat; + + private double levelRatio; + + private static int MAX_SOUND_LEVEL = Short.MAX_VALUE; + private static int MIN_SOUND_LEVEL = Short.MIN_VALUE; + + private int lastLevel = 0; + + private SoundLevelIndicatorListener listener = null; + + /** + * The minimum and maximum values of the scale + * @param minLevel min level. + * @param maxLevel max lavel. + * @param listener the listener of the sound level changes. + */ + public SoundLevelIndicatorEffect(int minLevel, int maxLevel, + SoundLevelIndicatorListener listener) + { + this.listener = listener; + + levelRatio = MAX_SOUND_LEVEL/(maxLevel - minLevel); + + supportedAudioFormats = new Format[]{ + new AudioFormat( + AudioFormat.LINEAR, + Format.NOT_SPECIFIED, + 16, + 1, + AudioFormat.LITTLE_ENDIAN, + AudioFormat.SIGNED, + 16, + Format.NOT_SPECIFIED, + Format.byteArray) + }; + } + + /** + * Lists all of the input formats that this codec accepts. + * @return An array that contains the supported input Formats. + */ + public Format[] getSupportedInputFormats() + { + return supportedAudioFormats; + } + + /** + * Lists the output formats that this codec can generate. + * @param input The Format of the data to be used + * as input to the plug-in. + * @return An array that contains the supported output Formats. + */ + public Format[] getSupportedOutputFormats(Format input) + { + return supportedAudioFormats; + } + + /** + * Sets the format of the data to be input to this codec. + * @param format The Format to be set. + * @return The Format that was set. + */ + public Format setInputFormat(Format format) + { + this.inputFormat = (AudioFormat)format; + return inputFormat; + } + + /** + * Sets the format for the data this codec outputs. + * @param format The Format to be set. + * @return The Format that was set. + */ + public Format setOutputFormat(Format format) + { + this.outputFormat = (AudioFormat)format; + return outputFormat; + } + + /** + * Performs the media processing defined by this codec. + * @param inputBuffer The Buffer that contains the media data + * to be processed. + * @param outputBuffer The Buffer in which to store + * the processed media data. + * @return BUFFER_PROCESSED_OK if the processing is successful. + * @see PlugIn + */ + public int process(Buffer inputBuffer, Buffer outputBuffer) + { + byte[] b = new byte[inputBuffer.getLength()]; + System.arraycopy(inputBuffer.getData(), inputBuffer.getOffset(), b, 0, b.length); + outputBuffer.setData(b); + + outputBuffer.setData(b); + outputBuffer.setFormat(inputBuffer.getFormat()); + outputBuffer.setLength(inputBuffer.getLength()); + outputBuffer.setOffset(inputBuffer.getOffset()); + outputBuffer.setHeader(inputBuffer.getHeader()); + outputBuffer.setSequenceNumber(inputBuffer.getSequenceNumber()); + outputBuffer.setTimeStamp(inputBuffer.getTimeStamp()); + outputBuffer.setFlags(inputBuffer.getFlags()); + outputBuffer.setDiscard(inputBuffer.isDiscard()); + outputBuffer.setEOM(inputBuffer.isEOM()); + outputBuffer.setDuration(inputBuffer.getDuration()); + + int newLevel = calculateCurrentSignalPower( + b, 0, b.length, levelRatio); + + if(newLevel != lastLevel) + listener.soundLevelChanged(newLevel); + + lastLevel = newLevel; + + return BUFFER_PROCESSED_OK; + } + + + /** + * Estimates the signal power and use the levelRatio to + * scale it to the needed levels. + * @param buff the buffer with the data. + * @param offset the offset that data starts. + * @param len the length of the data + * @param levelRatio the ratio for scaling to the needed levels + * @return the power of the signal in dB SWL. + */ + public static int calculateCurrentSignalPower( + byte[] buff, int offset, int len, double levelRatio) + { + if(len == 0) + return 0; + + int samplesNumber = len/2; + int absoluteMeanSoundLevel = 0; + // Do the processing + for (int i = 0; i < samplesNumber; i++) + { + int tempL = buff[offset++]; + int tempH = buff[offset++]; + int soundLevel = tempH << 8 | (tempL & 255); + + if (soundLevel > MAX_SOUND_LEVEL) + { + soundLevel = MAX_SOUND_LEVEL; + } else if (soundLevel < MIN_SOUND_LEVEL) { + soundLevel = MIN_SOUND_LEVEL; + } + + absoluteMeanSoundLevel += Math.abs(soundLevel); + } + + return (int)(absoluteMeanSoundLevel/samplesNumber/levelRatio); + } + + /** + * Gets the name of this plug-in as a human-readable string. + * @return A String that contains the descriptive name of the + * plug-in. + */ + public String getName() + { + return "SoundLevelIndicator Effect"; + } + + /** + * Opens this effect. + * @throws ResourceUnavailableException If all of the required resources + * cannot be acquired. + */ + public void open() + throws ResourceUnavailableException + { + } + + /** + * Closes this effect. + */ + public void close() + { + } + + /** + * Restes its state. + */ + public void reset() + { + } + + /** + * Obtain the collection of objects that + * control the object that implements this interface. + *

+ * + * If no controls are supported, a zero length + * array is returned. + * + * @return the collection of object controls + */ + public Object[] getControls() + { + return new Control[0]; + } + + /** + * Obtain the object that implements the specified + * Class or Interface + * The full class or interface name must be used. + *

+ * + * If the control is not supported then null + * is returned. + * + * @param controlType the control type to return. + * @return the object that implements the control, + * or null. + */ + public Object getControl(String controlType) + { + try + { + Class cls = Class.forName(controlType); + Object cs[] = getControls(); + for(int i = 0; i < cs.length; i++) + { + if(cls.isInstance(cs[i])) + { + return cs[i]; + } + } + return null; + + } + catch (Exception e) + { + return null; + } + } + + /** + * Lister for the changes in the sound level. + */ + public static interface SoundLevelIndicatorListener + { + /** + * Called when the sound level is changing. + * @param level the new level. + */ + public void soundLevelChanged(int level); + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java index 501204b54..30cf6b46c 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java @@ -17,9 +17,11 @@ import javax.media.rtp.*; import net.java.sip.communicator.impl.neomedia.*; +import net.java.sip.communicator.impl.neomedia.codec.audio.*; import net.java.sip.communicator.impl.neomedia.format.*; import net.java.sip.communicator.service.neomedia.*; import net.java.sip.communicator.service.neomedia.device.*; +import net.java.sip.communicator.service.neomedia.event.*; import net.java.sip.communicator.service.neomedia.format.*; import net.java.sip.communicator.util.*; @@ -86,15 +88,15 @@ public class MediaDeviceSession private ControllerListener playerControllerListener; /** - * The Players rendering ReceiveStreams on the + * The Processors rendering ReceiveStreams on the * MediaDevice represented by this instance. Associated with * DataSource because different ReceiveStreams may be * added with one and the same DataSource so it has to be clear - * when a new Player is to be created and when it is to be - * disposed. + * when a new Processor is to be created and when it is to be + * disposed. The Processor is used as a Player. */ - private final Map players - = new HashMap(); + private final Map players + = new HashMap(); /** * The JMF Processor which transcodes {@link #captureDevice} into @@ -200,7 +202,7 @@ protected void addReceiveStream( synchronized (players) { - Player player = players.get(receiveStreamDataSource); + Processor player = players.get(receiveStreamDataSource); if (player == null) { @@ -208,7 +210,7 @@ protected void addReceiveStream( try { - player = Manager.createPlayer(receiveStreamDataSource); + player = Manager.createProcessor(receiveStreamDataSource); } catch (IOException ioe) { @@ -227,29 +229,39 @@ protected void addReceiveStream( exception); else { - if (playerControllerListener == null) - playerControllerListener = new ControllerListener() - { - - /** - * Notifies this ControllerListener that - * the Controller which it is registered - * with has generated an event. - * - * @param event the ControllerEvent - * specifying the Controller which is the - * source of the event and the very type of the - * event - * @see ControllerListener#controllerUpdate( - * ControllerEvent) - */ - public void controllerUpdate(ControllerEvent event) - { - playerControllerUpdate(event); - } - }; - player.addControllerListener(playerControllerListener); - player.realize(); + waitForState(player, Processor.Configured); +// // here we add sound level indicator for every incoming +// //stream +// try +// { +// TrackControl tc[] = player.getTrackControls(); +// if (tc != null) +// { +// for (int i = 0; i < tc.length; i++) +// { +// if (tc[i].getFormat() instanceof AudioFormat) +// { +// // Assume there is only one audio track +// tc[i].setCodecChain(new Codec[]{ +// new SoundLevelIndicatorEffect()}); +// break; +// } +// } +// } +// } +// catch (UnsupportedPlugInException ex) +// { +// logger.error("The processor does not support effects", ex); +// } + // to use the processor as player we must se its + // content descriptor to null + player.setContentDescriptor(null); + + waitForState(player, Processor.Realized); + + player.start(); + + realizeComplete(player); if (logger.isTraceEnabled()) logger @@ -421,16 +433,17 @@ private void disconnectCaptureDevice() } /** - * Releases the resources allocated by a specific Player in the + * Releases the resources allocated by a specific Processor in the * course of its execution and prepares it to be garbage collected. + * The Processor is used as a Player. * - * @param player the Player to dispose of + * @param player the Processor to dispose of */ - protected void disposePlayer(Player player) + protected void disposePlayer(Processor player) { synchronized (players) { - Iterator> playerIter + Iterator> playerIter = players.entrySet().iterator(); while (playerIter.hasNext()) @@ -456,7 +469,7 @@ private void disposePlayers() { synchronized (players) { - for (Player player : getPlayers()) + for (Processor player : getPlayers()) disposePlayer(player); } } @@ -638,20 +651,21 @@ public DataSource getOutputDataSource() } /** - * Gets the Players rendering ReceiveStreams for this + * Gets the Processorss rendering ReceiveStreams for this * instance on its associated MediaDevice. The returned * List is a copy of the internal storage and, consequently, * modifications to it do not affect this instance. + * The Processors are used as a Players. * - * @return a new List of Players rendering + * @return a new List of Processors rendering * ReceiveStreams for this instance on its associated * MediaDevice */ - protected List getPlayers() + protected List getPlayers() { synchronized (players) { - return new ArrayList(players.values()); + return new ArrayList(players.values()); } } @@ -784,35 +798,6 @@ public List getSupportedFormats() return supportedMediaFormats; } - /** - * Gets notified about ControllerEvents generated by the - * Player instances in {@link #players}. - * - * @param event the ControllerEvent specifying the - * Controller which is the source of the event and the very type of - * the event - */ - private void playerControllerUpdate(ControllerEvent event) - { - if (event instanceof RealizeCompleteEvent) - { - Player player = (Player) event.getSourceController(); - - if (player != null) - { - if (logger.isTraceEnabled()) - logger - .trace( - "Realized Player with hashCode " - + player.hashCode()); - - player.start(); - - realizeComplete(player); - } - } - } - /** * Gets notified about ControllerEvents generated by * {@link #processor}. @@ -846,6 +831,33 @@ private void processorControllerUpdate(ControllerEvent event) if (format != null) setFormat(processor, format); + + if(NeomediaActivator.getMediaServiceImpl() + .getLocalSoundLevelListeners().size() > 0) + { + // here we add sound level indicator for captured media + // from the microphone if there are interested listeners + try + { + TrackControl tc[] = processor.getTrackControls(); + if (tc != null) + { + for (int i = 0; i < tc.length; i++) + { + if (tc[i].getFormat() instanceof AudioFormat) + { + addSpundLevelIndicator(tc[i]); + break; + } + } + } + } + catch (UnsupportedPlugInException ex) + { + logger.error( + "Unsupported sound level indicator effect", ex); + } + } } } else if (event instanceof ControllerClosedEvent) @@ -865,14 +877,40 @@ else if (event instanceof ControllerClosedEvent) } /** - * Notifies this instance that a specific Player of remote content - * has generated a RealizeCompleteEvent. Allows extenders to carry - * out additional processing on the Player. + * Creates sound level indicator effect and add it to the + * codec chain of the TrackControl and + * assumes there is only one audio track. + * @param tc the track control. + * @throws UnsupportedPlugInException + */ + private void addSpundLevelIndicator(TrackControl tc) + throws UnsupportedPlugInException + { + SoundLevelIndicatorEffect slie = new SoundLevelIndicatorEffect( + LocalUserSoundLevelEvent.MIN_LEVEL, + LocalUserSoundLevelEvent.MAX_LEVEL, + new SoundLevelIndicatorEffect.SoundLevelIndicatorListener() + { + public void soundLevelChanged(int level) + { + NeomediaActivator.getMediaServiceImpl() + .fireLocalUserSoundLevelEvent(level); + } + }); + // Assume there is only one audio track + tc.setCodecChain(new Codec[]{slie}); + } + + /** + * Notifies this instance that a specific Processor of + * remote content has generated a RealizeCompleteEvent. + * Allows extenders to carry out additional processing on the + * Processor. The Processor is used as a Player. * - * @param player the Player which is the source of a + * @param player the Processor which is the source of a * RealizeCompleteEvent */ - protected void realizeComplete(Player player) + protected void realizeComplete(Processor player) { } @@ -893,7 +931,7 @@ public void removeReceiveStream(ReceiveStream receiveStream) && !receiveStreams.containsValue(receiveStreamDataSource)) synchronized (players) { - Player player = players.get(receiveStreamDataSource); + Processor player = players.get(receiveStreamDataSource); if (player != null) disposePlayer(player); diff --git a/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java index f2f0b4798..0e4338438 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java @@ -86,18 +86,19 @@ protected void checkDevice(AbstractMediaDevice device) } /** - * Releases the resources allocated by a specific Player in the + * Releases the resources allocated by a specific Processor in the * course of its execution and prepares it to be garbage collected. If the - * specified Player is rendering video, notifies the + * specified Processor is rendering video, notifies the * VideoListeners of this instance that its visual * Component is to no longer be used by firing a * {@link VideoEvent#VIDEO_REMOVED} VideoEvent. * - * @param player the Player to dispose of + * @param player the Processor to dispose of, + * the processor is used as Player. * @see MediaDeviceSession#disposePlayer(Player) */ @Override - protected void disposePlayer(Player player) + protected void disposePlayer(Processor player) { /* @@ -159,7 +160,7 @@ protected boolean fireVideoEvent( */ public Component getVisualComponent() { - for (Player player : getPlayers()) + for (Processor player : getPlayers()) { Component visualComponent = getVisualComponent(player); @@ -170,17 +171,19 @@ public Component getVisualComponent() } /** - * Gets the visual Component of a specific Player if it + * Gets the visual Component of a specific Processor if it * has one and ignores the failure to access it if the specified - * Player is unrealized. + * Processor is unrealized. + * The Processor is used as Player. * * @param player the Player to get the visual Component of * if it has one * @return the visual Component of the specified Player if - * it has one; null if the specified Player does not have - * a visual Component or the Player is unrealized + * it has one; null if the specified Processor + * does not have a visual Component or + * the Processor is unrealized. */ - private static Component getVisualComponent(Player player) + private static Component getVisualComponent(Processor player) { Component visualComponent; @@ -204,15 +207,16 @@ private static Component getVisualComponent(Player player) } /** - * Notifies this instance that a specific Player of remote content - * has generated a RealizeCompleteEvent. + * Notifies this instance that a specific Processor of remote + * content has generated a RealizeCompleteEvent. + * The Processor is used as Player. * - * @param player the Player which is the source of a - * RealizeCompleteEvent + * @param player the Processor which is the source of a + * RealizeCompleteEvent. * @see MediaDeviceSession#realizeComplete(Player) */ @Override - protected void realizeComplete(Player player) + protected void realizeComplete(Processor player) { super.realizeComplete(player); diff --git a/src/net/java/sip/communicator/impl/protocol/gibberish/OperationSetTelephonyConferencingGibberishImpl.java b/src/net/java/sip/communicator/impl/protocol/gibberish/OperationSetTelephonyConferencingGibberishImpl.java index 225460578..cae3631d8 100644 --- a/src/net/java/sip/communicator/impl/protocol/gibberish/OperationSetTelephonyConferencingGibberishImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/gibberish/OperationSetTelephonyConferencingGibberishImpl.java @@ -82,19 +82,6 @@ public Call createConfCall(String[] callees) telephonyOpSet.fireCallEvent(CallEvent.CALL_INITIATED, newCall); - final Random random = new Random(); - Timer timer1 = new Timer(false); - timer1.scheduleAtFixedRate(new TimerTask() - { - @Override - public void run() - { - telephonyOpSet.fireLocalUserSoundLevelEvent( - protocolProvider, - random.nextInt(255)); - } - }, 500, 100); - return newCall; } diff --git a/src/net/java/sip/communicator/service/neomedia/AudioMediaStream.java b/src/net/java/sip/communicator/service/neomedia/AudioMediaStream.java index 242800cb0..d3a0dbff5 100644 --- a/src/net/java/sip/communicator/service/neomedia/AudioMediaStream.java +++ b/src/net/java/sip/communicator/service/neomedia/AudioMediaStream.java @@ -20,7 +20,7 @@ public interface AudioMediaStream /** * Adds listener to the list of SoundLevelListeners * registered to receive notifications for changes in the levels of - * conference participants that the remote party could be mixing. + * remote participant. * * @param listener the SoundLevelListener that we'd like to * register. @@ -36,6 +36,27 @@ public interface AudioMediaStream */ public void removeSoundLevelListener(SoundLevelListener listener); + /** + * Adds listener to the list of SoundLevelListeners + * registered to receive notifications for changes in the levels of + * conference participants that the remote party could be mixing. + * + * @param listener the SoundLevelListener that we'd like to + * register. + */ + public void addConferenceMemberSoundLevelListener( + SoundLevelListener listener); + + /** + * Removes listener from the list of SoundLevelListeners + * registered to receive notification events upon changes of the sound + * level. + * + * @param listener the listener that we'd like to unregister. + */ + public void removeConferenceMemberSoundLevelListener( + SoundLevelListener listener); + /** * Starts sending the specified DTMFTone until the * stopSendingDTMF() method is called. Callers should keep in mind diff --git a/src/net/java/sip/communicator/service/neomedia/MediaService.java b/src/net/java/sip/communicator/service/neomedia/MediaService.java index 0eff6a22a..444f47216 100644 --- a/src/net/java/sip/communicator/service/neomedia/MediaService.java +++ b/src/net/java/sip/communicator/service/neomedia/MediaService.java @@ -9,6 +9,7 @@ import java.util.*; import net.java.sip.communicator.service.neomedia.device.*; +import net.java.sip.communicator.service.neomedia.event.*; import net.java.sip.communicator.service.neomedia.format.*; /** @@ -87,4 +88,17 @@ public MediaStream createMediaStream(StreamConnector connector, * with the MediaStreams created by this MediaService */ public MediaFormatFactory getFormatFactory(); + + /** + * Adds the given LocalUserSoundLevelListener to this operation set. + * @param l the LocalUserSoundLevelListener to add + */ + public void addLocalUserSoundLevelListener(LocalUserSoundLevelListener l); + + /** + * Removes the given LocalUserSoundLevelListener from this + * operation set. + * @param l the LocalUserSoundLevelListener to remove + */ + public void removeLocalUserSoundLevelListener(LocalUserSoundLevelListener l); } diff --git a/src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelEvent.java b/src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelEvent.java similarity index 86% rename from src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelEvent.java rename to src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelEvent.java index 742b089b7..3e38c21f8 100644 --- a/src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelEvent.java +++ b/src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelEvent.java @@ -4,7 +4,7 @@ * Distributable under LGPL license. * See terms of license at gnu.org. */ -package net.java.sip.communicator.service.protocol.event; +package net.java.sip.communicator.service.neomedia.event; import java.util.*; @@ -38,15 +38,13 @@ public class LocalUserSoundLevelEvent /** * Creates an StreamSoundLevelEvent for the given callPeer * by indicating the current sound level of the audio stream. - * - * @param protocolProvider the ProtocolProviderService + * + * @param source the source of the new LocalUserSoundLevelEvent. * @param level the current sound level of the audio stream */ - public LocalUserSoundLevelEvent( - ProtocolProviderService protocolProvider, int level) + public LocalUserSoundLevelEvent(Object source, int level) { - super(protocolProvider); - + super(source); this.level = level; } diff --git a/src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelListener.java b/src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelListener.java similarity index 91% rename from src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelListener.java rename to src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelListener.java index 2a0bdb8d5..b6b37a75a 100644 --- a/src/net/java/sip/communicator/service/protocol/event/LocalUserSoundLevelListener.java +++ b/src/net/java/sip/communicator/service/neomedia/event/LocalUserSoundLevelListener.java @@ -4,7 +4,7 @@ * Distributable under LGPL license. * See terms of license at gnu.org. */ -package net.java.sip.communicator.service.protocol.event; +package net.java.sip.communicator.service.neomedia.event; /** * Notifies interested parties in sound level changes of the local user audio diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java index a01d31f87..307ffd1a9 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java @@ -32,12 +32,6 @@ public abstract class AbstractOperationSetBasicTelephony */ private final List callListeners = new Vector(); - /** - * A list of listeners registered for local user sound level events. - */ - private final List soundLevelListeners - = new Vector(); - /** * Registers listener with this provider so that it * could be notified when incoming calls are received. @@ -127,63 +121,4 @@ public void setMute(CallPeer peer, boolean mute) * this implementation takes inspiration from them. */ } - - /** - * Adds the given LocalUserSoundLevelListener to this operation set. - * @param l the LocalUserSoundLevelListener to add - */ - public void addLocalUserSoundLevelListener(LocalUserSoundLevelListener l) - { - synchronized(soundLevelListeners) - { - if (!soundLevelListeners.contains(l)) - soundLevelListeners.add(l); - } - } - - /** - * Removes the given LocalUserSoundLevelListener from this - * operation set. - * @param l the LocalUserSoundLevelListener to remove - */ - public void removeLocalUserSoundLevelListener(LocalUserSoundLevelListener l) - { - synchronized(soundLevelListeners) - { - soundLevelListeners.remove(l); - } - } - - /** - * Creates and dispatches a LocalUserSoundLevelEvent notifying - * registered listeners that the local user sound level has changed. - * - * @param protocolProvider the protocol provider for which the level is - * @param level the new level - */ - public void fireLocalUserSoundLevelEvent( - ProtocolProviderService protocolProvider, int level) - { - LocalUserSoundLevelEvent soundLevelEvent - = new LocalUserSoundLevelEvent(protocolProvider, level); - List listeners; - - synchronized (soundLevelListeners) - { - listeners = new ArrayList( - soundLevelListeners); - } - - logger.debug("Dispatching a LocalUserSoundLevelEvent to " - + listeners.size() - + " listeners. event is: " + soundLevelEvent); - - for (Iterator listenerIter - = listeners.iterator(); listenerIter.hasNext();) - { - LocalUserSoundLevelListener listener = listenerIter.next(); - - listener.localUserSoundLevelChanged(soundLevelEvent); - } - } } diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java index 23963e966..42af141f1 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java @@ -149,17 +149,4 @@ public void hangupCallPeer(CallPeer peer) * peer; otherwise, false */ public void setMute(CallPeer peer, boolean mute); - - /** - * Adds the given LocalUserSoundLevelListener to this operation set. - * @param l the LocalUserSoundLevelListener to add - */ - public void addLocalUserSoundLevelListener(LocalUserSoundLevelListener l); - - /** - * Removes the given LocalUserSoundLevelListener from this - * operation set. - * @param l the LocalUserSoundLevelListener to remove - */ - public void removeLocalUserSoundLevelListener(LocalUserSoundLevelListener l); }