/* * 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.protocol.jabber; import java.awt.*; import java.awt.event.*; import java.util.List; import net.java.sip.communicator.impl.protocol.jabber.extensions.inputevt.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import org.jivesoftware.smack.*; import org.jivesoftware.smack.filter.*; import org.jivesoftware.smack.packet.*; import org.jivesoftware.smackx.packet.*; // disambiguation /** * Implements all desktop sharing client-side related functions for Jabber * protocol. * * @author Sebastien Vincent */ public class OperationSetDesktopSharingClientJabberImpl extends AbstractOperationSetDesktopSharingClient <ProtocolProviderServiceJabberImpl> implements RegistrationStateChangeListener, PacketListener, PacketFilter { /** * Initializes a new <tt>OperationSetDesktopSharingClientJabberImpl</tt>. * * @param parentProvider the Jabber <tt>ProtocolProviderService</tt> * implementation which has requested the creation of the new instance and * for which the new instance is to provide desktop sharing. */ public OperationSetDesktopSharingClientJabberImpl( ProtocolProviderServiceJabberImpl parentProvider) { super(parentProvider); parentProvider.addRegistrationStateChangeListener(this); } /** * Send a keyboard notification. * * @param callPeer <tt>CallPeer</tt> that will be notified * @param event <tt>KeyEvent</tt> received and that will be send to remote * peer */ public void sendKeyboardEvent(CallPeer callPeer, KeyEvent event) { RemoteControlExtension payload = new RemoteControlExtension(event); this.sendRemoteControlExtension(callPeer, payload); } /** * Send a mouse notification. * * @param callPeer <tt>CallPeer</tt> that will be notified * @param event <tt>MouseEvent</tt> received and that will be send to remote * peer */ public void sendMouseEvent(CallPeer callPeer, MouseEvent event) { RemoteControlExtension payload = new RemoteControlExtension(event); this.sendRemoteControlExtension(callPeer, payload); } /** * Send a mouse notification for specific "moved" <tt>MouseEvent</tt>. As * controller computer could have smaller desktop that controlled ones, we * should take care to send the percentage of point x and point y. * * @param callPeer <tt>CallPeer</tt> that will be notified * @param event <tt>MouseEvent</tt> received and that will be send to remote * peer * @param videoPanelSize size of the panel that contains video */ public void sendMouseEvent(CallPeer callPeer, MouseEvent event, Dimension videoPanelSize) { RemoteControlExtension payload = new RemoteControlExtension(event, videoPanelSize); this.sendRemoteControlExtension(callPeer, payload); } /** * Send a mouse/keyboard/videoPanelSize notification. * * @param callPeer <tt>CallPeer</tt> that will be notified * @param payload The packet payload containing the * key/mouse/videoPanelSize event to send to remote peer */ private void sendRemoteControlExtension( CallPeer callPeer, RemoteControlExtension payload) { DiscoverInfo discoverInfo = ((CallPeerJabberImpl) callPeer).getDiscoveryInfo(); if(this.parentProvider.getDiscoveryManager() .includesFeature(InputEvtIQ.NAMESPACE_CLIENT) && discoverInfo != null && discoverInfo.containsFeature(InputEvtIQ.NAMESPACE_SERVER)) { InputEvtIQ inputIQ = new InputEvtIQ(); inputIQ.setAction(InputEvtAction.NOTIFY); inputIQ.setType(IQ.Type.SET); inputIQ.setFrom(parentProvider.getOurJID()); inputIQ.setTo(callPeer.getAddress()); inputIQ.addRemoteControl(payload); parentProvider.getConnection().sendPacket(inputIQ); } } /** * Implementation of method <tt>registrationStateChange</tt> from * interface RegistrationStateChangeListener for setting up (or down) * our <tt>InputEvtManager</tt> when an <tt>XMPPConnection</tt> is available * * @param evt the event received */ public void registrationStateChanged(RegistrationStateChangeEvent evt) { OperationSetDesktopSharingServerJabberImpl.registrationStateChanged( evt, this, this, this.parentProvider.getConnection()); } /** * Handles incoming inputevt packets and passes them to the corresponding * method based on their action. * * @param packet the packet to process. */ public void processPacket(Packet packet) { InputEvtIQ inputIQ = (InputEvtIQ)packet; //first ack all "set" requests. if(inputIQ.getType() == IQ.Type.SET && inputIQ.getAction() != InputEvtAction.NOTIFY) { IQ ack = IQ.createResultIQ(inputIQ); parentProvider.getConnection().sendPacket(ack); String callPeerID = inputIQ.getFrom(); if(callPeerID != null) { CallPeer callPeer = getListenerCallPeer(callPeerID); if(callPeer != null) { if(inputIQ.getAction() == InputEvtAction.START) { fireRemoteControlGranted(callPeer); } else if(inputIQ.getAction() == InputEvtAction.STOP) { fireRemoteControlRevoked(callPeer); } } } } } /** * Tests whether or not the specified packet should be handled by this * operation set. This method is called by smack prior to packet delivery * and it would only accept <tt>InputEvtIQ</tt>s. * * @param packet the packet to test. * @return true if and only if <tt>packet</tt> passes the filter. */ public boolean accept(Packet packet) { //we only handle InputEvtIQ-s return (packet instanceof InputEvtIQ); } /** * Returns the callPeer corresponding to the given callPeerAddress given in * parameter, if this callPeer exists in the listener list. * * @param callPeerAddress The XMPP address of the call peer to seek. * * @return The callPeer corresponding to the given callPeerAddress given in * parameter, if this callPeer exists in the listener list. null otherwise. */ protected CallPeer getListenerCallPeer(String callPeerAddress) { CallPeerJabberImpl callPeer; List<RemoteControlListener> listeners = getListeners(); for(int i = 0; i < listeners.size(); ++i) { callPeer = (CallPeerJabberImpl) listeners.get(i).getCallPeer(); if(callPeer.getAddress().equals(callPeerAddress)) { return callPeer; } } // If no peers corresponds, then return NULL. return null; } }