aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2010-12-17 14:21:32 +0000
committerDamian Minkov <damencho@jitsi.org>2010-12-17 14:21:32 +0000
commit5fcaeed371bcf2c2289976f0de40721e300529d4 (patch)
treee9de4a725eb1fefc5fca86f54938d697caa93e3d /src/net/java/sip/communicator
parent37826ceb132b911621d30cf498be71605a5a8063 (diff)
downloadjitsi-5fcaeed371bcf2c2289976f0de40721e300529d4.zip
jitsi-5fcaeed371bcf2c2289976f0de40721e300529d4.tar.gz
jitsi-5fcaeed371bcf2c2289976f0de40721e300529d4.tar.bz2
Introduce possibility to control capture volume from the GUI through media service. Add capture and playback volume buttons to fullscreen call dialog.
Diffstat (limited to 'src/net/java/sip/communicator')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java23
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/AbstractVolumeControlButton.java131
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java13
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java105
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/VolumeControlButton.java103
-rw-r--r--src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf1
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/AbstractVolumeControl.java (renamed from src/net/java/sip/communicator/impl/neomedia/VolumeControlImpl.java)46
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/InputVolumeControlImpl.java30
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java28
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/OutputVolumeControlImpl.java30
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java36
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java2
-rw-r--r--src/net/java/sip/communicator/service/neomedia/InputVolumeControl.java22
-rw-r--r--src/net/java/sip/communicator/service/neomedia/MediaService.java8
-rw-r--r--src/net/java/sip/communicator/service/neomedia/OutputVolumeControl.java22
-rw-r--r--src/net/java/sip/communicator/service/neomedia/VolumeControl.java7
17 files changed, 477 insertions, 132 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java b/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
index 9863c21..f15e38c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
@@ -53,6 +53,13 @@ public abstract class AbstractCallToggleButton
protected ImageID iconImageID;
/**
+ * Whether we should spawn action when clicking the button in new thread.
+ * Volume control buttons use this abstract button for its fullscreen view
+ * and don't need the new thread. Default is true, create new thread.
+ */
+ private boolean spawnActionInNewThread = true;
+
+ /**
* Initializes a new <tt>AbstractCallToggleButton</tt> instance which is to
* control a toggle action for a specific <tt>Call</tt>.
*
@@ -105,6 +112,16 @@ public abstract class AbstractCallToggleButton
}
/**
+ * Changes behaviour, whether we should start new thread for executing
+ * actions, buttonPressed().
+ * @param spawnActionInNewThread
+ */
+ public void setSpawnActionInNewThread(boolean spawnActionInNewThread)
+ {
+ this.spawnActionInNewThread = spawnActionInNewThread;
+ }
+
+ /**
* The button model of this call toggle button.
*/
private class CallToggleButtonModel
@@ -125,6 +142,12 @@ public abstract class AbstractCallToggleButton
public synchronized void actionPerformed(ActionEvent event)
{
+ if(!spawnActionInNewThread)
+ {
+ buttonPressed();
+ return;
+ }
+
if (runner == null)
{
runner = new Thread(this, LocalVideoButton.class.getName());
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/AbstractVolumeControlButton.java b/src/net/java/sip/communicator/impl/gui/main/call/AbstractVolumeControlButton.java
new file mode 100644
index 0000000..15bd738
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/AbstractVolumeControlButton.java
@@ -0,0 +1,131 @@
+/*
+ * 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.gui.main.call;
+
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.resources.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * The <tt>VolumeControlButton</tt> is the button shown in the call window,
+ * which allows to adjust the volume of your call.
+ *
+ * @author Yana Stamcheva
+ */
+public abstract class AbstractVolumeControlButton
+ extends AbstractCallToggleButton
+{
+ /**
+ * The multiplier would just convert the float volume value coming from
+ * the service to the int value needed for the volume control slider
+ * component.
+ */
+ private static final int MULTIPLIER = 100;
+
+ /**
+ * Creates an instance of <tt>VolumeControlButton</tt>.
+ */
+ public AbstractVolumeControlButton(
+ Call call,
+ final boolean fullScreen,
+ boolean selected,
+ ImageID iconImageID,
+ String toolTipTextKey)
+ {
+ super(call, fullScreen, selected, iconImageID, toolTipTextKey);
+
+ // we don't want new thread when button is pressed
+ setSpawnActionInNewThread(false);
+
+ // Loads the skin of this button.
+ loadSkin();
+
+ final JSlider volumeSlider
+ = new JSlider(JSlider.VERTICAL, 0, 100, 50);
+
+ volumeSlider.setPreferredSize(new Dimension(20, 100));
+
+ final VolumeControl volumeControl = getVolumeControl();
+
+ // Sets the minimum, maximum and default volume values for the volume
+ // slider.
+ if (volumeControl != null)
+ {
+ volumeSlider.setMinimum(
+ (int) (volumeControl.getMinValue()*MULTIPLIER));
+ volumeSlider.setMaximum(
+ (int) (volumeControl.getMaxValue()*MULTIPLIER));
+
+ volumeSlider.setValue(
+ (int) (volumeControl.getVolume()*MULTIPLIER));
+ }
+
+ // Adds a change listener to the slider in order to correctly set
+ // the volume through the VolumeControl service, on user change.
+ volumeSlider.addChangeListener(new ChangeListener()
+ {
+ public void stateChanged(ChangeEvent e)
+ {
+ JSlider source = (JSlider) e.getSource();
+ int volume = source.getValue();
+
+ // Set the volume to the volume control.
+ volumeControl.setVolume((float) volume/MULTIPLIER);
+ }
+ });
+
+ // Creates the menu that would contain the volume control component.
+ final JPopupMenu sliderMenu = new JPopupMenu();
+ sliderMenu.setInvoker(this);
+ sliderMenu.add(volumeSlider);
+
+ this.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent arg0)
+ {
+ Point location = new Point(getX(), getY() + getHeight());
+
+ SwingUtilities.convertPointToScreen(location,
+ AbstractVolumeControlButton.this.getParent());
+
+ if(fullScreen)
+ location.setLocation(location.getX(),
+ location.getY()
+ - sliderMenu.getPreferredSize().getHeight()
+ - getHeight());
+
+ if (volumeControl != null)
+ volumeSlider.setValue(
+ (int) (volumeControl.getVolume()*MULTIPLIER));
+
+ sliderMenu.setLocation(location);
+
+ sliderMenu.setVisible(!sliderMenu.isVisible());
+ }
+ });
+ }
+
+ /**
+ *
+ */
+ public void buttonPressed()
+ {
+ // just a # bypass the toggle functionality as we don't use it
+ setSelected(!isSelected());
+ }
+
+ /**
+ * Volume control used by the button.
+ * @return volume control used by the button.
+ */
+ public abstract VolumeControl getVolumeControl();
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java
index b826452..f3261c0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java
@@ -292,6 +292,7 @@ public class CallDialog
settingsPanel.add(conferenceButton);
settingsPanel.add(holdButton);
settingsPanel.add(muteButton);
+ settingsPanel.add(volumeControlButton);
settingsPanel.add(recordButton);
if (!isLastConference)
@@ -306,8 +307,6 @@ public class CallDialog
addOneToOneSpecificComponents();
}
- settingsPanel.add(volumeControlButton);
-
buttonsPanel.add(settingsPanel, BorderLayout.WEST);
buttonsPanel.add(hangupButton, BorderLayout.EAST);
@@ -1089,4 +1088,14 @@ public class CallDialog
settingsPanel.repaint();
}
}
+
+ /**
+ * Checks whether recording is currently enabled or not, state retrieved
+ * from call record button state.
+ * @return
+ */
+ public boolean isRecordingStarted()
+ {
+ return recordButton.isSelected();
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java b/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java
index d6f4111..ca967c7 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java
@@ -6,7 +6,10 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
+import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.neomedia.event.*;
import net.java.sip.communicator.service.protocol.*;
/**
@@ -18,14 +21,24 @@ import net.java.sip.communicator.service.protocol.*;
* @author Dmitri Melnikov
*/
public class MuteButton
- extends AbstractCallToggleButton
+ extends AbstractVolumeControlButton
+ implements VolumeChangeListener,
+ Runnable
{
/**
- * The serialization-related version of the <tt>MuteButton</tt> class
- * explicitly defined to silence a related warning (e.g. in Eclipse IDE)
- * since the <tt>MuteButton</tt> class does not add instance fields.
+ * Mutes the call in other thread.
*/
- private static final long serialVersionUID = 0L;
+ private Thread muteRunner;
+
+ /**
+ * Our volume control.
+ */
+ private VolumeControl volumeControl;
+
+ /**
+ * Current mute state.
+ */
+ private boolean mute = false;
/**
* Initializes a new <tt>MuteButton</tt> instance which is to mute the audio
@@ -52,18 +65,72 @@ public class MuteButton
*/
public MuteButton(Call call, boolean fullScreen, boolean selected)
{
- super(
- call,
- fullScreen,
- selected,
- ImageLoader.MUTE_BUTTON,
+ super(call, fullScreen, selected, ImageLoader.MUTE_BUTTON,
"service.gui.MUTE_BUTTON_TOOL_TIP");
+
+ this.mute = selected;
+ }
+
+ /**
+ * Volume control used by the button.
+ *
+ * @return volume control used by the button.
+ */
+ @Override
+ public VolumeControl getVolumeControl()
+ {
+ if(volumeControl == null)
+ {
+ volumeControl = GuiActivator.getMediaService()
+ .getInputVolumeControl();
+
+ volumeControl.addVolumeChangeListener(this);
+ }
+
+ return volumeControl;
}
/**
* Mutes or unmutes the associated <tt>Call</tt> upon clicking this button.
*/
- public void buttonPressed()
+ public void toggleMute()
+ {
+ if (muteRunner == null)
+ {
+ muteRunner = new Thread(this, getToolTipText());
+ muteRunner.setDaemon(true);
+
+ setEnabled(false);
+ muteRunner.start();
+ }
+ }
+
+ /**
+ * Toggles state on call in different thread.
+ */
+ public void run()
+ {
+ try
+ {
+ doRun();
+ }
+ finally
+ {
+ synchronized (this)
+ {
+ if (Thread.currentThread().equals(muteRunner))
+ {
+ muteRunner = null;
+ setEnabled(true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Do the actual muting/unmuting.
+ */
+ private void doRun()
{
if (call != null)
{
@@ -71,7 +138,21 @@ public class MuteButton
= call.getProtocolProvider().getOperationSet(
OperationSetBasicTelephony.class);
- telephony.setMute(call, isSelected());
+ mute = !mute;
+ telephony.setMute(call, mute);
}
}
+
+ /**
+ * Event fired when volume has changed.
+ *
+ * @param volumeChangeEvent the volume change event.
+ */
+ public void volumeChange(VolumeChangeEvent volumeChangeEvent)
+ {
+ if(volumeChangeEvent.getLevel() == 0)
+ toggleMute();
+ else if(mute)
+ toggleMute();
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
index e327714..5ec36d4 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
@@ -267,6 +267,8 @@ public class OneToOneCallPanel
new MuteButton(call,
true,
callPeer.isMute()),
+ new VolumeControlButton(true),
+ new RecordButton(call, true, callDialog.isRecordingStarted()),
CallPeerRendererUtils.createExitFullScreenButton(this)
};
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlButton.java b/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlButton.java
index f5fad5e..67ec262 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlButton.java
@@ -6,111 +6,38 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
-import java.awt.*;
-import java.awt.event.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.neomedia.*;
-import net.java.sip.communicator.util.skin.*;
-import net.java.sip.communicator.util.swing.*;
/**
* The <tt>VolumeControlButton</tt> is the button shown in the call window,
- * which allows to adjust the volume of your call.
+ * which allows to adjust the playback volume of your call.
*
* @author Yana Stamcheva
*/
public class VolumeControlButton
- extends SIPCommButton
- implements Skinnable
+ extends AbstractVolumeControlButton
{
- /**
- * The multiplier would just convert the float volume value coming from
- * the service to the int value needed for the volume control slider
- * component.
- */
- private static final int MULTIPLIER = 100;
-
- /**
- * Creates an instance of <tt>VolumeControlButton</tt>.
- */
public VolumeControlButton()
{
- // Loads the skin of this button.
- loadSkin();
-
- setToolTipText(GuiActivator.getResources().getI18NString(
- "service.gui.VOLUME_CONTROL_TOOL_TIP"));
-
- final JSlider volumeSlider
- = new JSlider(JSlider.VERTICAL, 0, 100, 50);
-
- volumeSlider.setPreferredSize(new Dimension(20, 100));
-
- final VolumeControl volumeControl
- = GuiActivator.getMediaService().getVolumeControl();
-
- // Sets the minimum, maximum and default volume values for the volume
- // slider.
- if (volumeControl != null)
- {
- volumeSlider.setMinimum(
- (int) (volumeControl.getMinValue()*MULTIPLIER));
- volumeSlider.setMaximum(
- (int) (volumeControl.getMaxValue()*MULTIPLIER));
-
- volumeSlider.setValue(
- (int) (volumeControl.getVolume()*MULTIPLIER));
- }
-
- // Adds a change listener to the slider in order to correctly set
- // the volume through the VolumeControl service, on user change.
- volumeSlider.addChangeListener(new ChangeListener()
- {
- public void stateChanged(ChangeEvent e)
- {
- JSlider source = (JSlider) e.getSource();
- int volume = source.getValue();
-
- // Set the volume to the volume control.
- volumeControl.setVolume((float) volume/MULTIPLIER);
- }
- });
-
- // Creates the menu that would contain the volume control component.
- final JPopupMenu sliderMenu = new JPopupMenu();
- sliderMenu.setInvoker(this);
- sliderMenu.add(volumeSlider);
-
- this.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent arg0)
- {
- Point location = new Point(getX(), getY() + getHeight());
-
- SwingUtilities.convertPointToScreen(location,
- VolumeControlButton.this.getParent());
-
- sliderMenu.setLocation(location);
+ this(false);
+ }
- sliderMenu.setVisible(!sliderMenu.isVisible());
- }
- });
+ public VolumeControlButton(boolean fullScreen)
+ {
+ super(null, fullScreen, false, ImageLoader.VOLUME_CONTROL_BUTTON,
+ "service.gui.VOLUME_CONTROL_TOOL_TIP");
}
/**
- * Loads volume control button skin.
+ * Volume control used by the button.
+ *
+ * @return volume control used by the button.
*/
- public void loadSkin()
+ @Override
+ public VolumeControl getVolumeControl()
{
- this.setBackgroundImage(ImageLoader.getImage(
- ImageLoader.CALL_SETTING_BUTTON_BG));
-
- this.setIconImage(ImageLoader.getImage(
- ImageLoader.VOLUME_CONTROL_BUTTON));
+ return GuiActivator.getMediaService().getOutputVolumeControl();
}
-} \ No newline at end of file
+}
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 f6bf8aa..7e6162f 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
@@ -30,6 +30,7 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.shutdown,
net.java.sip.communicator.service.systray,
net.java.sip.communicator.service.neomedia,
+ net.java.sip.communicator.service.neomedia.event,
net.java.sip.communicator.service.neomedia.device,
net.java.sip.communicator.service.neomedia.format,
net.java.sip.communicator.service.contactsource,
diff --git a/src/net/java/sip/communicator/impl/neomedia/VolumeControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/AbstractVolumeControl.java
index 89bbc58..a03b50f 100644
--- a/src/net/java/sip/communicator/impl/neomedia/VolumeControlImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/AbstractVolumeControl.java
@@ -16,15 +16,15 @@ import java.util.*;
import java.util.List;
/**
- * Controls media service playback volume. If a volume level is set
- * we change it on all current players, as we synchronize volume on all players.
- * Implements interface exposed from media service, also implements
- * the interface used in the Renderer part of JMF and merges the two
+ * Controls media service volume input or output. If a playback volume level
+ * is set we change it on all current players, as we synchronize volume
+ * on all players. Implements interface exposed from media service, also
+ * implements the interface used in the Renderer part of JMF and merges the two
* functionalities to work as one.
*
* @author Damian Minkov
*/
-public class VolumeControlImpl
+public abstract class AbstractVolumeControl
implements VolumeControl,
GainControl
{
@@ -33,7 +33,7 @@ public class VolumeControlImpl
* its instances for logging output.
*/
private static final Logger logger
- = Logger.getLogger(VolumeControlImpl.class);
+ = Logger.getLogger(AbstractVolumeControl.class);
/**
* The minimum volume level we can handle.
@@ -73,7 +73,7 @@ public class VolumeControlImpl
private boolean currentMuteState = false;
/**
- * Current playback level in db.
+ * Current level in db.
*/
private float db;
@@ -86,27 +86,27 @@ public class VolumeControlImpl
* Creates volume control instance and initialise initial level value
* if stored in config service.
*/
- VolumeControlImpl()
+ AbstractVolumeControl()
{
// read initial level from config service if any
- String initialPlaybackLevel =
+ String initialLevel =
NeomediaActivator.getConfigurationService()
- .getString(PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME);
+ .getString(getStoreLevelPropertyName());
try
{
- if(initialPlaybackLevel != null)
+ if(initialLevel != null)
{
- currentVolumeLevel = Float.valueOf(initialPlaybackLevel);
+ currentVolumeLevel = Float.valueOf(initialLevel);
initialVolumeLevel = currentVolumeLevel;
if(logger.isDebugEnabled())
- logger.debug("Restore playback volume: "
+ logger.debug("Restore volume: "
+ currentVolumeLevel);
}
}
catch(Throwable t)
{
- logger.warn("Error restoring playback volume", t);
+ logger.warn("Error restoring volume", t);
}
}
@@ -213,7 +213,7 @@ public class VolumeControlImpl
// save the level change, so we can restore it on next run
NeomediaActivator.getConfigurationService().setProperty(
- PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME,
+ getStoreLevelPropertyName(),
String.valueOf(currentVolumeLevel));
float f1 = value / initialVolumeLevel;
@@ -227,9 +227,9 @@ public class VolumeControlImpl
}
/**
- * Mutes current sound playback.
+ * Mutes current sound.
*
- * @param mute mutes/unmutes playback.
+ * @param mute mutes/unmutes.
*/
public void setMute(boolean mute)
{
@@ -244,9 +244,9 @@ public class VolumeControlImpl
}
/**
- * Get mute state of sound playback.
+ * Get mute state of sound.
*
- * @return mute state of sound playback.
+ * @return mute state of sound.
*/
public boolean getMute()
{
@@ -404,4 +404,12 @@ public class VolumeControlImpl
{
return null;
}
+
+ /**
+ * Implementers return the property name they use to store
+ * sound level information.
+ *
+ * @return sound level property name for storing configuration.
+ */
+ abstract String getStoreLevelPropertyName();
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/InputVolumeControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/InputVolumeControlImpl.java
new file mode 100644
index 0000000..3078e1d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/neomedia/InputVolumeControlImpl.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import net.java.sip.communicator.service.neomedia.*;
+
+/**
+ * Controls media service capture volume.
+ *
+ * @author Damian Minkov
+ */
+public class InputVolumeControlImpl
+ extends AbstractVolumeControl
+ implements InputVolumeControl
+{
+ /**
+ * Returns the property we use to store input sound level.
+ *
+ * @return sound level property name for storing configuration.
+ */
+ @Override
+ String getStoreLevelPropertyName()
+ {
+ return CAPTURE_VOLUME_LEVEL_PROPERTY_NAME;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
index 1a0eaec..aea92bd 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
@@ -122,7 +122,12 @@ public class MediaServiceImpl
/**
* The volume control of the media service playback.
*/
- private static VolumeControl volumeControl;
+ private static OutputVolumeControl outputVolumeControl;
+
+ /**
+ * The volume control of the media service capture.
+ */
+ private static InputVolumeControl inputVolumeControl;
/**
* Create a <tt>MediaStream</tt> which will use a specific
@@ -544,12 +549,25 @@ public class MediaServiceImpl
*
* @return the volume playback control.
*/
- public VolumeControl getVolumeControl()
+ public OutputVolumeControl getOutputVolumeControl()
+ {
+ if(outputVolumeControl == null)
+ outputVolumeControl = new OutputVolumeControlImpl();
+
+ return outputVolumeControl;
+ }
+
+ /**
+ * Returns the control that handles current capture levels.
+ *
+ * @return the volume capture control.
+ */
+ public InputVolumeControl getInputVolumeControl()
{
- if(volumeControl == null)
- volumeControl = new VolumeControlImpl();
+ if(inputVolumeControl == null)
+ inputVolumeControl = new InputVolumeControlImpl();
- return volumeControl;
+ return inputVolumeControl;
}
/**
diff --git a/src/net/java/sip/communicator/impl/neomedia/OutputVolumeControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/OutputVolumeControlImpl.java
new file mode 100644
index 0000000..6106cbf
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/neomedia/OutputVolumeControlImpl.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import net.java.sip.communicator.service.neomedia.*;
+
+/**
+ * Controls media service playback volume.
+ *
+ * @author Damian Minkov
+ */
+public class OutputVolumeControlImpl
+ extends AbstractVolumeControl
+ implements OutputVolumeControl
+{
+ /**
+ * Returns the property we use to store output sound level.
+ *
+ * @return sound level property name for storing configuration.
+ */
+ @Override
+ String getStoreLevelPropertyName()
+ {
+ return PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java
index d415fdc..10bae4a 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java
@@ -7,6 +7,7 @@
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio;
import java.io.*;
+import java.util.*;
import javax.media.*;
import javax.media.control.*;
@@ -87,6 +88,11 @@ public class PortAudioStream
private boolean streamIsBusy = false;
/**
+ * Volume Control used to control volume of current captured media.
+ */
+ private GainControl volumeControl = null;
+
+ /**
* Initializes a new <tt>PortAudioStream</tt> instance which is to have its
* <tt>Format</tt>-related information abstracted by a specific
* <tt>FormatControl</tt>.
@@ -104,6 +110,9 @@ public class PortAudioStream
super(formatControl);
this.audioQualityImprovement = audioQualityImprovement;
+
+ this.volumeControl = (GainControl)NeomediaActivator
+ .getMediaServiceImpl().getInputVolumeControl();
}
/**
@@ -178,6 +187,33 @@ public class PortAudioStream
throw ioex;
}
+ // if we have some volume setting apply them
+ if(volumeControl != null)
+ {
+ if(volumeControl.getMute())
+ {
+ Arrays.fill(bufferData, (byte) 0);
+ }
+ else if(volumeControl.getDB() != 0)
+ {
+ // increase/decrease a little more than
+ // if using levels for factor
+ // we use factor = pow(10, dB/10),
+ // but level = pow(10, dB/20);
+ double factor = Math.pow(10, (volumeControl.getDB() / 10d));
+
+ for (int i = 0; i < bufferData.length; i+=2)
+ {
+ short s = (short)((bufferData[i]&0xff)
+ | (bufferData[i + 1]<<8));
+ s = (short)(s*factor);
+
+ bufferData[i] = (byte) s;
+ bufferData[i+1] = (byte) (s >> 8);
+ }
+ }
+ }
+
long bufferTimeStamp = System.nanoTime();
buffer.setFlags(Buffer.FLAG_SYSTEM_TIME);
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java
index 5bcff9b..7c663f3 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java
@@ -172,7 +172,7 @@ public class PortAudioRenderer
{
if(enableVolumeControl)
this.gainControl = (GainControl)NeomediaActivator
- .getMediaServiceImpl().getVolumeControl();
+ .getMediaServiceImpl().getOutputVolumeControl();
}
/**
diff --git a/src/net/java/sip/communicator/service/neomedia/InputVolumeControl.java b/src/net/java/sip/communicator/service/neomedia/InputVolumeControl.java
new file mode 100644
index 0000000..2f1f6a2
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/InputVolumeControl.java
@@ -0,0 +1,22 @@
+/*
+ * 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.service.neomedia;
+
+/**
+ * Controls the capture volume in media service.
+ *
+ * @author Damian Minkov
+ */
+public interface InputVolumeControl
+ extends VolumeControl
+{
+ /**
+ * Property for storing level into configuration.
+ */
+ public final static String CAPTURE_VOLUME_LEVEL_PROPERTY_NAME
+ = "net.java.sip.communicator.service.media.CAPTURE_VOLUME_LEVEL";
+}
diff --git a/src/net/java/sip/communicator/service/neomedia/MediaService.java b/src/net/java/sip/communicator/service/neomedia/MediaService.java
index 58f5273..4f93530 100644
--- a/src/net/java/sip/communicator/service/neomedia/MediaService.java
+++ b/src/net/java/sip/communicator/service/neomedia/MediaService.java
@@ -142,7 +142,13 @@ public interface MediaService
* Returns the control that handles current playback levels.
* @return the volume playback control.
*/
- public VolumeControl getVolumeControl();
+ public OutputVolumeControl getOutputVolumeControl();
+
+ /**
+ * Returns the control that handles current capture levels.
+ * @return the volume capture control.
+ */
+ public InputVolumeControl getInputVolumeControl();
/**
* Get available <tt>ScreenDevice</tt>s.
diff --git a/src/net/java/sip/communicator/service/neomedia/OutputVolumeControl.java b/src/net/java/sip/communicator/service/neomedia/OutputVolumeControl.java
new file mode 100644
index 0000000..53b6d26
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/OutputVolumeControl.java
@@ -0,0 +1,22 @@
+/*
+ * 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.service.neomedia;
+
+/**
+ * Controls the playback volume in media service.
+ *
+ * @author Damian Minkov
+ */
+public interface OutputVolumeControl
+ extends VolumeControl
+{
+ /**
+ * Property for storing level into configuration.
+ */
+ public final static String PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME
+ = "net.java.sip.communicator.service.media.PLAYBACK_VOLUME_LEVEL";
+}
diff --git a/src/net/java/sip/communicator/service/neomedia/VolumeControl.java b/src/net/java/sip/communicator/service/neomedia/VolumeControl.java
index 5dbf25d..e93df44 100644
--- a/src/net/java/sip/communicator/service/neomedia/VolumeControl.java
+++ b/src/net/java/sip/communicator/service/neomedia/VolumeControl.java
@@ -9,15 +9,14 @@ package net.java.sip.communicator.service.neomedia;
import net.java.sip.communicator.service.neomedia.event.*;
/**
- * Controls the playback volume in media service.
+ * Control for volume level in media service.
+ * @see InputVolumeControl
+ * @see OutputVolumeControl
*
* @author Damian Minkov
*/
public interface VolumeControl
{
- public final static String PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME
- = "net.java.sip.communicator.service.media.PLAYBACK_VOLUME_LEVEL";
-
/**
* Current volume value.
* @return the current volume level.