/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Timer;
import javax.swing.*;
import javax.swing.event.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.resources.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.event.*;
/**
* Represents an UI means to mute the audio stream sent in an associated
* <tt>Call</tt>.
*
* @author Lubomir Marinov
* @author Yana Stamcheva
* @author Dmitri Melnikov
* @author Damian Minkov
*/
public class InputVolumeControlButton
extends AbstractCallToggleButton
implements VolumeChangeListener,
Runnable
{
/**
* Mutes the call in other thread.
*/
private Thread muteRunner;
/**
* Our volume control.
*/
private final VolumeControl volumeControl;
/**
* The slider popup menu.
*/
private final JPopupMenu sliderMenu;
/**
* Current mute state.
*/
private boolean mute = false;
private boolean sliderMenuIsVisible = false;
/**
* The <tt>CallConference</tt> (i.e. telephony conference-related state)
* depicted by this instance.
*/
private final CallConference callConference;
/**
* Initializes a new <tt>MuteButton</tt> instance which is to mute the audio
* stream to a specific <tt>Call</tt>.
*
* @param callConference <tt>CallConference</tt> (i.e. telephony
* conference-related state) depicted by this instance and whose audio
* stream is to be muted upon performing its action
* @param iconImageID the icon image
* @param pressedIconImageID the <tt>ImageID</tt> of the image to be used
* as the icon in the pressed button state of the new instance
* @param selected <tt>true</tt> if the new toggle button is to be initially
* selected; otherwise, <tt>false</tt>
* @param inSettingsPanel <tt>true</tt> when the button is used in a menu,
* to use different background.
*/
public InputVolumeControlButton(CallConference callConference,
ImageID iconImageID,
ImageID pressedIconImageID,
boolean inSettingsPanel,
boolean selected)
{
super(null,
inSettingsPanel,
selected,
iconImageID,
pressedIconImageID,
"service.gui.MUTE_BUTTON_TOOL_TIP");
this.callConference = callConference;
this.mute = selected;
volumeControl = getVolumeControl();
// Creates the menu that would contain the volume control component.
sliderMenu
= new VolumeControlSlider(volumeControl, JSlider.VERTICAL)
.getPopupMenu();
sliderMenu.setInvoker(this);
addMouseListener(new MouseAdapter()
{
TimerTask timerTask;
@Override
public void mousePressed(MouseEvent mouseevent)
{
Timer timer = new Timer();
timerTask = new TimerTask()
{
@Override
public void run()
{
showSliderMenu();
}
};
timer.schedule(timerTask, 1000);
}
@Override
public void mouseReleased(MouseEvent mouseevent)
{
if (!sliderMenuIsVisible)
{
if (timerTask != null)
{
timerTask.cancel();
}
}
else
{
setSelected(!isSelected());
}
}
});
}
/**
* Volume control used by the button.
*
* @return volume control used by the button.
*/
private VolumeControl getVolumeControl()
{
VolumeControl volumeControl
= GuiActivator.getMediaService().getInputVolumeControl();
volumeControl.addVolumeChangeListener(this);
return volumeControl;
}
private void showSliderMenu()
{
Point location = new Point(getX(), getY() + getHeight());
SwingUtilities.convertPointToScreen(location,
InputVolumeControlButton.this.getParent());
if(isFullScreen())
{
location.setLocation(
location.getX(),
location.getY()
- sliderMenu.getPreferredSize().getHeight()
- getHeight());
}
sliderMenu.setLocation(location);
sliderMenu.addPopupMenuListener(
new PopupMenuListener()
{
public void popupMenuWillBecomeVisible(PopupMenuEvent ev)
{
sliderMenuIsVisible = true;
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent ev)
{
sliderMenuIsVisible = false;
}
public void popupMenuCanceled(PopupMenuEvent ev)
{
}
});
sliderMenu.setVisible(!sliderMenu.isVisible());
}
/**
* Mutes or unmutes the associated <tt>Call</tt> upon clicking this button.
*/
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 (callConference != null)
{
mute = !mute;
for(Call call : callConference.getCalls())
{
OperationSetBasicTelephony<?> telephony
= call.getProtocolProvider().getOperationSet(
OperationSetBasicTelephony.class);
telephony.setMute(call, mute);
}
// We make sure that the button state corresponds to the mute state.
setSelected(mute);
// If we unmute the microphone and the volume control is set to min,
// make sure that the volume control is restored to the initial
// state.
if (!mute
&& volumeControl.getVolume() == volumeControl.getMinValue())
{
volumeControl.setVolume(
(volumeControl.getMaxValue()
- volumeControl.getMinValue())/2);
}
}
}
/**
* 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();
}
/**
* Notifies this <tt>AbstractCallToggleButton</tt> that its associated
* action has been performed and that it should execute its very logic.
*/
@Override
public void buttonPressed()
{
if (!sliderMenuIsVisible)
toggleMute();
}
}