mirror of https://github.com/sipwise/jitsi.git
parent
24382db153
commit
990eee6bd8
|
After Width: | Height: | Size: 189 B |
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 java.awt.event.*;
|
||||
|
||||
import net.java.sip.communicator.impl.gui.*;
|
||||
import net.java.sip.communicator.impl.gui.utils.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import net.java.sip.communicator.util.swing.*;
|
||||
|
||||
/**
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class LocalVideoButton
|
||||
extends SIPCommToggleButton
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(LocalVideoButton.class);
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public LocalVideoButton(Call call)
|
||||
{
|
||||
setBgImage(ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG));
|
||||
setBgRolloverImage(
|
||||
ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG));
|
||||
setIconImage(ImageLoader.getImage(ImageLoader.LOCAL_VIDEO_BUTTON));
|
||||
setPressedImage(
|
||||
ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_PRESSED_BG));
|
||||
|
||||
setModel(new LocalVideoButtonModel(call));
|
||||
setToolTipText(GuiActivator.getResources().getI18NString(
|
||||
"service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP"));
|
||||
}
|
||||
|
||||
private static class LocalVideoButtonModel
|
||||
extends ToggleButtonModel
|
||||
implements ActionListener,
|
||||
Runnable
|
||||
{
|
||||
private final Call call;
|
||||
|
||||
private Thread runner;
|
||||
|
||||
public LocalVideoButtonModel(Call call)
|
||||
{
|
||||
this.call = call;
|
||||
|
||||
addActionListener(this);
|
||||
}
|
||||
|
||||
public boolean isSelected()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void actionPerformed(ActionEvent event)
|
||||
{
|
||||
if (runner == null)
|
||||
{
|
||||
runner = new Thread(this, LocalVideoButton.class.getName());
|
||||
runner.setDaemon(true);
|
||||
|
||||
setEnabled(false);
|
||||
runner.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
doRun();
|
||||
}
|
||||
finally
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (Thread.currentThread().equals(runner))
|
||||
{
|
||||
runner = null;
|
||||
setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doRun()
|
||||
{
|
||||
OperationSetVideoTelephony telephony = (OperationSetVideoTelephony)
|
||||
call.getProtocolProvider()
|
||||
.getOperationSet(OperationSetVideoTelephony.class);
|
||||
|
||||
if (telephony != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
telephony.setLocalVideoAllowed(
|
||||
call,
|
||||
!telephony.isLocalVideoAllowed(call));
|
||||
}
|
||||
catch (OperationFailedException ex)
|
||||
{
|
||||
logger.error(
|
||||
"Failed to toggle the streaming of local video.",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,230 +1,364 @@
|
||||
/*
|
||||
* 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.protocol.sip;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import net.java.sip.communicator.service.media.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
|
||||
/**
|
||||
* Implements <code>OperationSetVideoTelephony</code> in order to give access to
|
||||
* video-specific functionality in the SIP protocol implementation such as
|
||||
* visual <code>Component</code>s displaying video and listening to dynamic
|
||||
* availability of such <code>Component</code>s. Because the video in the SIP
|
||||
* protocol implementation is provided by the <code>CallSession</code>, this
|
||||
* <code>OperationSetVideoTelephony</code> just delegates to the
|
||||
* <code>CallSession</code> while hiding the <code>CallSession</code> as the
|
||||
* provider of the video and pretending this
|
||||
* <code>OperationSetVideoTelephony</code> is the provider because other
|
||||
* implementation may not provider their video through the
|
||||
* <code>CallSession</code>.
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class OperationSetVideoTelephonySipImpl
|
||||
implements OperationSetVideoTelephony
|
||||
{
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation. Because other OperationSetVideoTelephony implementations
|
||||
* may not provide their video through the CallSession, this implementation
|
||||
* promotes itself as the provider of the video by replacing the CallSession
|
||||
* in the VideoEvents it fires.
|
||||
*/
|
||||
public void addVideoListener(CallParticipant participant,
|
||||
VideoListener listener)
|
||||
{
|
||||
if (listener == null)
|
||||
throw new NullPointerException("listener");
|
||||
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession()
|
||||
.addVideoListener(
|
||||
new InternalVideoListener(this, participant, listener));
|
||||
}
|
||||
|
||||
public Component createLocalVisualComponent(CallParticipant participant,
|
||||
VideoListener listener) throws OperationFailedException
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
if (callSession != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return callSession.createLocalVisualComponent(listener);
|
||||
}
|
||||
catch (MediaException ex)
|
||||
{
|
||||
throw new OperationFailedException(
|
||||
"Failed to create visual Component for local video (capture).",
|
||||
OperationFailedException.INTERNAL_ERROR, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void disposeLocalVisualComponent(CallParticipant participant,
|
||||
Component component)
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
if (callSession != null)
|
||||
{
|
||||
callSession.disposeLocalVisualComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation.
|
||||
*/
|
||||
public Component[] getVisualComponents(CallParticipant participant)
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
return (callSession != null) ? callSession.getVisualComponents()
|
||||
: new Component[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation. Because other OperationSetVideoTelephony implementations
|
||||
* may not provide their video through the CallSession, this implementation
|
||||
* promotes itself as the provider of the video by replacing the CallSession
|
||||
* in the VideoEvents it fires.
|
||||
*/
|
||||
public void removeVideoListener(CallParticipant participant,
|
||||
VideoListener listener)
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession()
|
||||
.removeVideoListener(
|
||||
new InternalVideoListener(this, participant, listener));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a <code>VideoListener</code> which forwards notifications to a
|
||||
* specific delegate <code>VideoListener</code> and hides the original
|
||||
* <code>VideoEvent</code> sender from it by pretending the sender is a
|
||||
* specific <code>OperationSetVideoTelephony</code>. It's necessary in order
|
||||
* to hide from the <code>VideoListener</code>s the fact that the video of
|
||||
* the SIP protocol implementation is managed by <code>CallSession</code>.
|
||||
*/
|
||||
private static class InternalVideoListener
|
||||
implements VideoListener
|
||||
{
|
||||
|
||||
/**
|
||||
* The <code>VideoListener</code> this implementation hides the original
|
||||
* <code>VideoEvent</code> source from.
|
||||
*/
|
||||
private final VideoListener delegate;
|
||||
|
||||
/**
|
||||
* The <code>CallParticipant</code> whose videos {@link #delegate} is
|
||||
* interested in.
|
||||
*/
|
||||
private final CallParticipant participant;
|
||||
|
||||
/**
|
||||
* The <code>OperationSetVideoTelephony</code> which is to be presented
|
||||
* as the source of the <code>VideoEvents</code> forwarded to
|
||||
* {@link #delegate}.
|
||||
*/
|
||||
private final OperationSetVideoTelephony telephony;
|
||||
|
||||
/**
|
||||
* Initializes a new <code>InternalVideoListener</code> which is to
|
||||
* impersonate the sources of <code>VideoEvents</code> with a specific
|
||||
* <code>OperationSetVideoTelephony</code> for a specific
|
||||
* <code>VideoListener</code> interested in the videos of a specific
|
||||
* <code>CallParticipant</code>.
|
||||
*
|
||||
* @param telephony the <code>OperationSetVideoTelephony</code> which is
|
||||
* to be stated as the source of the <code>VideoEvent</code>
|
||||
* sent to the specified delegate <code>VideoListener</code>
|
||||
* @param participant the <code>CallParticipant</code> whose videos the
|
||||
* specified delegate <code>VideoListener</code> is
|
||||
* interested in
|
||||
* @param delegate the <code>VideoListener</code> which shouldn't know
|
||||
* that the videos in the SIP protocol implementation is
|
||||
* managed by the CallSession and not by the specified
|
||||
* <code>telephony</code>
|
||||
*/
|
||||
public InternalVideoListener(OperationSetVideoTelephony telephony,
|
||||
CallParticipant participant, VideoListener delegate)
|
||||
{
|
||||
if (participant == null)
|
||||
throw new NullPointerException("participant");
|
||||
|
||||
this.telephony = telephony;
|
||||
this.participant = participant;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two InternalVideoListeners are equal if they impersonate the sources
|
||||
* of VideoEvents with equal OperationSetVideoTelephonies for equal
|
||||
* delegate VideoListeners added to equal CallParticipants.
|
||||
*/
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (other == this)
|
||||
return true;
|
||||
if ((other == null) || !other.getClass().equals(getClass()))
|
||||
return false;
|
||||
|
||||
InternalVideoListener otherListener = (InternalVideoListener) other;
|
||||
|
||||
return otherListener.telephony.equals(telephony)
|
||||
&& otherListener.participant.equals(participant)
|
||||
&& otherListener.delegate.equals(delegate);
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return (telephony.hashCode() << 16) + (delegate.hashCode() >> 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon receiving a VideoEvent, sends to delegate a new VideoEvent of
|
||||
* the same type and with the same visual Component but with the source
|
||||
* of the event being set to #telephony. Thus the fact that the
|
||||
* CallSession is the original source is hidden from the clients of
|
||||
* OperationSetVideoTelephony.
|
||||
*/
|
||||
public void videoAdded(VideoEvent event)
|
||||
{
|
||||
delegate.videoAdded(new VideoEvent(this, event.getType(), event
|
||||
.getVisualComponent(), event.getOrigin()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon receiving a VideoEvent, sends to delegate a new VideoEvent of
|
||||
* the same type and with the same visual Component but with the source
|
||||
* of the event being set to #telephony. Thus the fact that the
|
||||
* CallSession is the original source is hidden from the clients of
|
||||
* OperationSetVideoTelephony.
|
||||
*/
|
||||
public void videoRemoved(VideoEvent event)
|
||||
{
|
||||
delegate.videoAdded(new VideoEvent(this, event.getType(), event
|
||||
.getVisualComponent(), event.getOrigin()));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.protocol.sip;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.service.media.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* Implements <code>OperationSetVideoTelephony</code> in order to give access to
|
||||
* video-specific functionality in the SIP protocol implementation such as
|
||||
* visual <code>Component</code>s displaying video and listening to dynamic
|
||||
* availability of such <code>Component</code>s. Because the video in the SIP
|
||||
* protocol implementation is provided by the <code>CallSession</code>, this
|
||||
* <code>OperationSetVideoTelephony</code> just delegates to the
|
||||
* <code>CallSession</code> while hiding the <code>CallSession</code> as the
|
||||
* provider of the video and pretending this
|
||||
* <code>OperationSetVideoTelephony</code> is the provider because other
|
||||
* implementation may not provider their video through the
|
||||
* <code>CallSession</code>.
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class OperationSetVideoTelephonySipImpl
|
||||
implements OperationSetVideoTelephony
|
||||
{
|
||||
|
||||
/**
|
||||
* The telephony-related functionality this extension builds upon.
|
||||
*/
|
||||
private final OperationSetBasicTelephonySipImpl basicTelephony;
|
||||
|
||||
/**
|
||||
* Initializes a new <code>OperationSetVideoTelephonySipImpl</code> instance
|
||||
* which builds upon the telephony-related functionality of a specific
|
||||
* <code>OperationSetBasicTelephonySipImpl</code>.
|
||||
*
|
||||
* @param basicTelephony the <code>OperationSetBasicTelephonySipImpl</code>
|
||||
* the new extension should build upon
|
||||
*/
|
||||
public OperationSetVideoTelephonySipImpl(
|
||||
OperationSetBasicTelephonySipImpl basicTelephony)
|
||||
{
|
||||
this.basicTelephony = basicTelephony;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation. Because other OperationSetVideoTelephony implementations
|
||||
* may not provide their video through the CallSession, this implementation
|
||||
* promotes itself as the provider of the video by replacing the CallSession
|
||||
* in the VideoEvents it fires.
|
||||
*/
|
||||
public void addVideoListener(CallParticipant participant,
|
||||
VideoListener listener)
|
||||
{
|
||||
if (listener == null)
|
||||
throw new NullPointerException("listener");
|
||||
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession()
|
||||
.addVideoListener(
|
||||
new InternalVideoListener(this, participant, listener));
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#createLocalVisualComponent(
|
||||
* CallParticipant, VideoListener). Delegates to CallSession#createLocalVisualComponent(
|
||||
* VideoListener) of the Call of the specified CallParticipant because the
|
||||
* CallSession manages the visual components which represent local video.
|
||||
*/
|
||||
public Component createLocalVisualComponent(CallParticipant participant,
|
||||
VideoListener listener) throws OperationFailedException
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
if (callSession != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return callSession.createLocalVisualComponent(listener);
|
||||
}
|
||||
catch (MediaException ex)
|
||||
{
|
||||
throw new OperationFailedException(
|
||||
"Failed to create visual Component for local video (capture).",
|
||||
OperationFailedException.INTERNAL_ERROR, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#disposeLocalVisualComponent(
|
||||
* CallParticipant, Component). Delegates to CallSession#disposeLocalVisualComponent(
|
||||
* Component) of the Call of the specified CallParticipant because the
|
||||
* CallSession manages the visual components which represent local video.
|
||||
*/
|
||||
public void disposeLocalVisualComponent(CallParticipant participant,
|
||||
Component component)
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
if (callSession != null)
|
||||
callSession.disposeLocalVisualComponent(component);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation.
|
||||
*/
|
||||
public Component[] getVisualComponents(CallParticipant participant)
|
||||
{
|
||||
CallSession callSession =
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession();
|
||||
|
||||
return (callSession != null) ? callSession.getVisualComponents()
|
||||
: new Component[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates to the CallSession of the Call of the specified CallParticipant
|
||||
* because the video is provided by the CallSession in the SIP protocol
|
||||
* implementation. Because other OperationSetVideoTelephony implementations
|
||||
* may not provide their video through the CallSession, this implementation
|
||||
* promotes itself as the provider of the video by replacing the CallSession
|
||||
* in the VideoEvents it fires.
|
||||
*/
|
||||
public void removeVideoListener(CallParticipant participant,
|
||||
VideoListener listener)
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
((CallSipImpl) participant.getCall()).getMediaCallSession()
|
||||
.removeVideoListener(
|
||||
new InternalVideoListener(this, participant, listener));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#setLocalVideoAllowed(Call,
|
||||
* boolean). Modifies the local media setup to reflect the requested setting
|
||||
* for the streaming of the local video and then re-invites all
|
||||
* CallParticipants to re-negotiate the modified media setup.
|
||||
*/
|
||||
public void setLocalVideoAllowed(Call call, boolean allowed)
|
||||
throws OperationFailedException
|
||||
{
|
||||
|
||||
/*
|
||||
* Modify the local media setup to reflect the requested setting for the
|
||||
* streaming of the local video.
|
||||
*/
|
||||
CallSipImpl sipCall = (CallSipImpl) call;
|
||||
CallSession callSession = sipCall.getMediaCallSession();
|
||||
|
||||
try
|
||||
{
|
||||
callSession.setLocalVideoAllowed(allowed);
|
||||
}
|
||||
catch (MediaException ex)
|
||||
{
|
||||
throw new OperationFailedException(
|
||||
"Failed to allow/disallow the streaming of local video.",
|
||||
OperationFailedException.INTERNAL_ERROR, ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the local state has been modified, re-invite all
|
||||
* CallParticipants to re-negotiate the modified media setup.
|
||||
*/
|
||||
Iterator<CallParticipant> participants = call.getCallParticipants();
|
||||
while (participants.hasNext())
|
||||
{
|
||||
CallParticipantSipImpl participant
|
||||
= (CallParticipantSipImpl) participants.next();
|
||||
String sdpOffer = null;
|
||||
|
||||
try
|
||||
{
|
||||
sdpOffer
|
||||
= callSession.createSdpOffer(
|
||||
participant.getSdpDescription());
|
||||
}
|
||||
catch (MediaException ex)
|
||||
{
|
||||
throw new OperationFailedException(
|
||||
"Failed to create re-invite offer for participant "
|
||||
+ participant,
|
||||
OperationFailedException.INTERNAL_ERROR,
|
||||
ex);
|
||||
}
|
||||
|
||||
basicTelephony.sendInviteRequest(participant, sdpOffer);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#isLocalVideoAllowed(Call).
|
||||
* Delegates to CallSession#isLocalVideoAllowed() of the specified Call.
|
||||
*/
|
||||
public boolean isLocalVideoAllowed(Call call)
|
||||
{
|
||||
return ((CallSipImpl) call).getMediaCallSession().isLocalVideoAllowed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#isLocalVideoStreaming(Call).
|
||||
* Delegates to CallSession#isLocalVideoStreaming() of the specified Call.
|
||||
*/
|
||||
public boolean isLocalVideoStreaming(Call call)
|
||||
{
|
||||
return ((CallSipImpl) call)
|
||||
.getMediaCallSession().isLocalVideoStreaming();
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#addPropertyChangeListener(Call,
|
||||
* PropertyChangeListener). Delegates to CallSession#addPropertyChangeListener(
|
||||
* PropertyChangeListener) of the specified Call because CallSession
|
||||
* contains the properties associated with a Call.
|
||||
*/
|
||||
public void addPropertyChangeListener(
|
||||
Call call, PropertyChangeListener listener)
|
||||
{
|
||||
((CallSipImpl) call)
|
||||
.getMediaCallSession().addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements OperationSetVideoTelephony#removePropertyChangeListener(Call,
|
||||
* PropertyChangeListener). Delegates to CallSession#removePropertyChangeListener(
|
||||
* PropertyChangeListener) of the specified Call because CallSession
|
||||
* contains the properties associated with a Call.
|
||||
*/
|
||||
public void removePropertyChangeListener(
|
||||
Call call, PropertyChangeListener listener)
|
||||
{
|
||||
((CallSipImpl) call)
|
||||
.getMediaCallSession().removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a <code>VideoListener</code> which forwards notifications to a
|
||||
* specific delegate <code>VideoListener</code> and hides the original
|
||||
* <code>VideoEvent</code> sender from it by pretending the sender is a
|
||||
* specific <code>OperationSetVideoTelephony</code>. It's necessary in order
|
||||
* to hide from the <code>VideoListener</code>s the fact that the video of
|
||||
* the SIP protocol implementation is managed by <code>CallSession</code>.
|
||||
*/
|
||||
private static class InternalVideoListener
|
||||
implements VideoListener
|
||||
{
|
||||
|
||||
/**
|
||||
* The <code>VideoListener</code> this implementation hides the original
|
||||
* <code>VideoEvent</code> source from.
|
||||
*/
|
||||
private final VideoListener delegate;
|
||||
|
||||
/**
|
||||
* The <code>CallParticipant</code> whose videos {@link #delegate} is
|
||||
* interested in.
|
||||
*/
|
||||
private final CallParticipant participant;
|
||||
|
||||
/**
|
||||
* The <code>OperationSetVideoTelephony</code> which is to be presented
|
||||
* as the source of the <code>VideoEvents</code> forwarded to
|
||||
* {@link #delegate}.
|
||||
*/
|
||||
private final OperationSetVideoTelephony telephony;
|
||||
|
||||
/**
|
||||
* Initializes a new <code>InternalVideoListener</code> which is to
|
||||
* impersonate the sources of <code>VideoEvents</code> with a specific
|
||||
* <code>OperationSetVideoTelephony</code> for a specific
|
||||
* <code>VideoListener</code> interested in the videos of a specific
|
||||
* <code>CallParticipant</code>.
|
||||
*
|
||||
* @param telephony the <code>OperationSetVideoTelephony</code> which is
|
||||
* to be stated as the source of the <code>VideoEvent</code>
|
||||
* sent to the specified delegate <code>VideoListener</code>
|
||||
* @param participant the <code>CallParticipant</code> whose videos the
|
||||
* specified delegate <code>VideoListener</code> is
|
||||
* interested in
|
||||
* @param delegate the <code>VideoListener</code> which shouldn't know
|
||||
* that the videos in the SIP protocol implementation is
|
||||
* managed by the CallSession and not by the specified
|
||||
* <code>telephony</code>
|
||||
*/
|
||||
public InternalVideoListener(OperationSetVideoTelephony telephony,
|
||||
CallParticipant participant, VideoListener delegate)
|
||||
{
|
||||
if (participant == null)
|
||||
throw new NullPointerException("participant");
|
||||
|
||||
this.telephony = telephony;
|
||||
this.participant = participant;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two InternalVideoListeners are equal if they impersonate the sources
|
||||
* of VideoEvents with equal OperationSetVideoTelephonies for equal
|
||||
* delegate VideoListeners added to equal CallParticipants.
|
||||
*/
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (other == this)
|
||||
return true;
|
||||
if ((other == null) || !other.getClass().equals(getClass()))
|
||||
return false;
|
||||
|
||||
InternalVideoListener otherListener = (InternalVideoListener) other;
|
||||
|
||||
return otherListener.telephony.equals(telephony)
|
||||
&& otherListener.participant.equals(participant)
|
||||
&& otherListener.delegate.equals(delegate);
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return (telephony.hashCode() << 16) + (delegate.hashCode() >> 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon receiving a VideoEvent, sends to delegate a new VideoEvent of
|
||||
* the same type and with the same visual Component but with the source
|
||||
* of the event being set to #telephony. Thus the fact that the
|
||||
* CallSession is the original source is hidden from the clients of
|
||||
* OperationSetVideoTelephony.
|
||||
*/
|
||||
public void videoAdded(VideoEvent event)
|
||||
{
|
||||
delegate.videoAdded(new VideoEvent(this, event.getType(), event
|
||||
.getVisualComponent(), event.getOrigin()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon receiving a VideoEvent, sends to delegate a new VideoEvent of
|
||||
* the same type and with the same visual Component but with the source
|
||||
* of the event being set to #telephony. Thus the fact that the
|
||||
* CallSession is the original source is hidden from the clients of
|
||||
* OperationSetVideoTelephony.
|
||||
*/
|
||||
public void videoRemoved(VideoEvent event)
|
||||
{
|
||||
delegate.videoAdded(new VideoEvent(this, event.getType(), event
|
||||
.getVisualComponent(), event.getOrigin()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,67 +1,181 @@
|
||||
/*
|
||||
* 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.protocol;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
|
||||
/**
|
||||
* Represents an <code>OperationSet</code> giving access to video-specific
|
||||
* functionality in telephony such as visual <code>Component</code>s displaying
|
||||
* video and listening to dynamic availability of such <code>Component</code>s.
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public interface OperationSetVideoTelephony
|
||||
extends OperationSet
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds a specific <code>VideoListener</code> to this telephony in order to
|
||||
* receive notifications when visual/video <code>Component</code>s are being
|
||||
* added and removed for a specific <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose video the
|
||||
* specified listener is to be notified about
|
||||
* @param listener the <code>VideoListener</code> to be notified when
|
||||
* visual/video <code>Component</code>s are being added or
|
||||
* removed for <code>participant</code>
|
||||
*/
|
||||
void addVideoListener(CallParticipant participant, VideoListener listener);
|
||||
|
||||
Component createLocalVisualComponent(CallParticipant participant,
|
||||
VideoListener listener) throws OperationFailedException;
|
||||
|
||||
void disposeLocalVisualComponent(CallParticipant participant,
|
||||
Component component);
|
||||
|
||||
/**
|
||||
* Gets the visual/video <code>Component</code>s available in this telephony
|
||||
* for a specific <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose videos are to
|
||||
* be retrieved
|
||||
* @return an array of the visual <code>Component</code>s available in this
|
||||
* telephony for the specified <code>participant</code>
|
||||
*/
|
||||
Component[] getVisualComponents(CallParticipant participant);
|
||||
|
||||
/**
|
||||
* Removes a specific <code>VideoListener</code> from this telephony in
|
||||
* order to no longer have it receive notifications when visual/video
|
||||
* <code>Component</code>s are being added and removed for a specific
|
||||
* <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose video the
|
||||
* specified listener is to no longer be notified about
|
||||
* @param listener the <code>VideoListener</code> to no longer be notified
|
||||
* when visual/video <code>Component</code>s are being added or
|
||||
* removed for <code>participant</code>
|
||||
*/
|
||||
void removeVideoListener(CallParticipant participant, VideoListener listener);
|
||||
}
|
||||
/*
|
||||
* 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.protocol;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import net.java.sip.communicator.service.media.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* Represents an <code>OperationSet</code> giving access to video-specific
|
||||
* functionality in telephony such as visual <code>Component</code>s displaying
|
||||
* video and listening to dynamic availability of such <code>Component</code>s.
|
||||
*
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public interface OperationSetVideoTelephony
|
||||
extends OperationSet
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds a specific <code>VideoListener</code> to this telephony in order to
|
||||
* receive notifications when visual/video <code>Component</code>s are being
|
||||
* added and removed for a specific <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose video the
|
||||
* specified listener is to be notified about
|
||||
* @param listener the <code>VideoListener</code> to be notified when
|
||||
* visual/video <code>Component</code>s are being added or
|
||||
* removed for <code>participant</code>
|
||||
*/
|
||||
public void addVideoListener(
|
||||
CallParticipant participant, VideoListener listener);
|
||||
|
||||
/**
|
||||
* Creates a visual <code>Component</code> which depicts the local video
|
||||
* being streamed to a specific <code>CallParticipant</code>. The returned
|
||||
* visual <code>Component</code> should be disposed when it is no longer
|
||||
* required through {@link #disposeLocalVisualComponent(CallParticipant, Component) disposeLocalVisualComponent}.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> to whom the local
|
||||
* video which is to be depicted by the returned visual
|
||||
* <code>Component</code> is being streamed
|
||||
* @param listener if not <tt>null</tt>, a <code>VideoListener</code> to
|
||||
* track the progress of the creation in case this telephony
|
||||
* chooses to perform it asynchronously and to not return the
|
||||
* created visual <code>Component</code> immediately/as the
|
||||
* result of this method call
|
||||
* @return a visual <code>Component</code> which depicts the local video
|
||||
* being streamed to the specified <code>CallParticipant</code> if
|
||||
* this telephony chooses to carry out the creation synchronously;
|
||||
* <tt>null</tt> if this telephony chooses to create the requested
|
||||
* visual <code>Component</code> asynchronously.
|
||||
*/
|
||||
public Component createLocalVisualComponent(
|
||||
CallParticipant participant, VideoListener listener)
|
||||
throws OperationFailedException;
|
||||
|
||||
/**
|
||||
* Disposes of a visual <code>Component</code> depicting the local video for
|
||||
* a specific <code>CallParticipant</code> (previously obtained through
|
||||
* {@link createLocalVisualComponent(CallParticipant, VideoListener) createLocalVisualComponent}).
|
||||
* The disposal may include, but is not limited to, releasing the
|
||||
* <code>Player</code> which provides the <code>component</code> and renders
|
||||
* the local video into it, disconnecting from the video capture device.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> for whom the visual
|
||||
* <code>Component</code> depicts the local video
|
||||
* @param component the visual <code>Component</code> depicting the local
|
||||
* video to be disposed
|
||||
*/
|
||||
public void disposeLocalVisualComponent(
|
||||
CallParticipant participant, Component component);
|
||||
|
||||
/**
|
||||
* Gets the visual/video <code>Component</code>s available in this telephony
|
||||
* for a specific <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose videos are to
|
||||
* be retrieved
|
||||
* @return an array of the visual <code>Component</code>s available in this
|
||||
* telephony for the specified <code>participant</code>
|
||||
*/
|
||||
public Component[] getVisualComponents(CallParticipant participant);
|
||||
|
||||
/**
|
||||
* Removes a specific <code>VideoListener</code> from this telephony in
|
||||
* order to no longer have it receive notifications when visual/video
|
||||
* <code>Component</code>s are being added and removed for a specific
|
||||
* <code>CallParticipant</code>.
|
||||
*
|
||||
* @param participant the <code>CallParticipant</code> whose video the
|
||||
* specified listener is to no longer be notified about
|
||||
* @param listener the <code>VideoListener</code> to no longer be notified
|
||||
* when visual/video <code>Component</code>s are being added or
|
||||
* removed for <code>participant</code>
|
||||
*/
|
||||
public void removeVideoListener(
|
||||
CallParticipant participant, VideoListener listener);
|
||||
|
||||
/**
|
||||
* Sets the indicator which determines whether the streaming of local video
|
||||
* in a specific <code>Call</code> is allowed. The setting does not reflect
|
||||
* the availability of actual video capture devices, it just expresses the
|
||||
* desire of the user to have the local video streamed in the case the
|
||||
* system is actually able to do so.
|
||||
*
|
||||
* @param call the <code>Call</code> to allow/disallow the streaming of
|
||||
* local video for
|
||||
* @param allowed <tt>true</tt> to allow the streaming of local video for
|
||||
* the specified <code>Call</code>; <tt>false</tt> to disallow it
|
||||
*/
|
||||
public void setLocalVideoAllowed(Call call, boolean allowed)
|
||||
throws OperationFailedException;
|
||||
|
||||
/**
|
||||
* Gets the indicator which determines whether the streaming of local video
|
||||
* in a specific <code>Call</code> is allowed. The setting does not reflect
|
||||
* the availability of actual video capture devices, it just expresses the
|
||||
* desire of the user to have the local video streamed in the case the
|
||||
* system is actually able to do so.
|
||||
*
|
||||
* @param call the <code>Call</code> to get the indicator of
|
||||
* @return <tt>true</tt> if the streaming of local video for the specified
|
||||
* <code>Call</code> is allowed; otherwise, <tt>false</tt>
|
||||
*/
|
||||
public boolean isLocalVideoAllowed(Call call);
|
||||
|
||||
/**
|
||||
* The property which indicates whether a specific <code>Call</code> is
|
||||
* currently streaming the local video (to a remote destination).
|
||||
*/
|
||||
public static final String LOCAL_VIDEO_STREAMING
|
||||
= CallSession.LOCAL_VIDEO_STREAMING;
|
||||
|
||||
/**
|
||||
* Gets the indicator which determines whether a specific <code>Call</code>
|
||||
* is currently streaming the local video (to a remote destination).
|
||||
*
|
||||
* @param call the <code>Call</code> to get the indicator of
|
||||
* @return <tt>true</tt> if the specified <code>Call</code> is currently
|
||||
* streaming the local video (to a remote destination); otherwise,
|
||||
* <tt>false</tt>
|
||||
*/
|
||||
public boolean isLocalVideoStreaming(Call call);
|
||||
|
||||
/**
|
||||
* Adds a specific <code>PropertyChangeListener</code> to the list of
|
||||
* listeners which get notified when the properties (e.g.
|
||||
* {@link #LOCAL_VIDEO_STREAMING}) associated with a specific
|
||||
* <code>Call</code> change their values.
|
||||
*
|
||||
* @param call the <code>Call</code> to start listening to the changes of
|
||||
* the property values of
|
||||
* @param listener the <code>PropertyChangeListener</code> to be notified
|
||||
* when the properties associated with the specified
|
||||
* <code>Call</code> change their values
|
||||
*/
|
||||
public void addPropertyChangeListener(
|
||||
Call call, PropertyChangeListener listener);
|
||||
|
||||
/**
|
||||
* Removes a specific <code>PropertyChangeListener</code> from the list of
|
||||
* listeners which get notified when the properties (e.g.
|
||||
* {@link #LOCAL_VIDEO_STREAMING}) associated with a specific
|
||||
* <code>Call</code> change their values.
|
||||
*
|
||||
* @param call the <code>Call</code> to stop listening to the changes of the
|
||||
* property values of
|
||||
* @param listener the <code>PropertyChangeListener</code> to no longer be
|
||||
* notified when the properties associated with the specified
|
||||
* <code>Call</code> change their values
|
||||
*/
|
||||
public void removePropertyChangeListener(
|
||||
Call call, PropertyChangeListener listener);
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class PropertyChangeNotifier
|
||||
{
|
||||
private final List<PropertyChangeListener> listeners
|
||||
= new Vector<PropertyChangeListener>();
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
synchronized(listeners)
|
||||
{
|
||||
if (!listeners.contains(listener))
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
synchronized(listeners)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
protected void firePropertyChange(String property, Object oldValue,
|
||||
Object newValue)
|
||||
{
|
||||
PropertyChangeListener[] listeners;
|
||||
synchronized (this.listeners)
|
||||
{
|
||||
listeners
|
||||
= this.listeners.toArray(
|
||||
new PropertyChangeListener[this.listeners.size()]);
|
||||
}
|
||||
|
||||
PropertyChangeEvent event = new PropertyChangeEvent(
|
||||
getPropertyChangeSource(property, oldValue, newValue),
|
||||
property,
|
||||
oldValue,
|
||||
newValue);
|
||||
|
||||
for (PropertyChangeListener listener : listeners)
|
||||
listener.propertyChange(event);
|
||||
}
|
||||
|
||||
protected Object getPropertyChangeSource(String property, Object oldValue,
|
||||
Object newValue)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
/**
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class PropertyChangeSupport
|
||||
extends PropertyChangeNotifier
|
||||
{
|
||||
private final Object source;
|
||||
|
||||
public PropertyChangeSupport(Object source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public void firePropertyChange(String property, Object oldValue,
|
||||
Object newValue)
|
||||
{
|
||||
super.firePropertyChange(property, oldValue, newValue);
|
||||
}
|
||||
|
||||
protected Object getPropertyChangeSource(String property, Object oldValue,
|
||||
Object newValue)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue