diff -r 6c2c4bfa43d0 -r d7ddcccdff8a doc/asmack-beem/beem_patches/50-remove-jingle_mediaimpl.patch --- a/doc/asmack-beem/beem_patches/50-remove-jingle_mediaimpl.patch Tue Jan 18 00:26:02 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4039 +0,0 @@ -Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (working copy) -@@ -1,92 +0,0 @@ --/** -- * $RCSfile: TestMediaSession.java,v $ -- * $Revision: 1.1 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.test; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * This Class implements a complete JingleMediaSession for unit testing. -- * -- * @author Thiago Camargo -- */ --public class TestMediaSession extends JingleMediaSession { -- -- /** -- * Creates a TestMediaSession with defined payload type, remote and local candidates -- * -- * @param payloadType Payload of the jmf -- * @param remote the remote information. The candidate that the jmf will be sent to. -- * @param local the local information. The candidate that will receive the jmf -- * @param locator media locator -- */ -- public TestMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, -- final String locator, JingleSession jingleSession) { -- super(payloadType, remote, local, "Test", jingleSession); -- initialize(); -- } -- -- /** -- * Initialize the screen share channels. -- */ -- public void initialize() { -- -- } -- -- /** -- * Starts transmission and for NAT Traversal reasons start receiving also. -- */ -- public void startTrasmit() { -- -- } -- -- /** -- * Set transmit activity. If the active is true, the instance should trasmit. -- * If it is set to false, the instance should pause transmit. -- * -- * @param active active state -- */ -- public void setTrasmit(boolean active) { -- -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void startReceive() { -- // Do nothing -- } -- -- /** -- * Stops transmission and for NAT Traversal reasons stop receiving also. -- */ -- public void stopTrasmit() { -- -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void stopReceive() { -- -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (working copy) -@@ -1,93 +0,0 @@ --/** -- * $RCSfile: TestMediaManager.java,v $ -- * $Revision: 1.3 $ -- * $Date: 25/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.test; -- --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; --import org.jivesoftware.smackx.jingle.JingleSession; -- --import java.util.*; -- --/** -- * Implements a MediaManager for test purposes. -- * -- * @author Thiago Camargo -- */ -- --public class TestMediaManager extends JingleMediaManager { -- -- public static final String MEDIA_NAME = "TestMedia"; -- -- private List payloads = new ArrayList(); -- -- private PayloadType preferredPayloadType = null; -- -- public TestMediaManager(JingleTransportManager transportManager) { -- super(transportManager); -- } -- -- /** -- * Return all supported Payloads for this Manager. -- * -- * @return The Payload List -- */ -- public List getPayloads() { -- return payloads; -- } -- -- public void setPayloads(List payloads) { -- this.payloads.addAll(payloads); -- } -- -- /** -- * Returns a new JingleMediaSession -- * -- * @param payloadType payloadType -- * @param remote remote Candidate -- * @param local local Candidate -- * @return JingleMediaSession JingleMediaSession -- */ -- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, -- final TransportCandidate local, final JingleSession jingleSession) { -- TestMediaSession session = null; -- -- session = new TestMediaSession(payloadType, remote, local, "", jingleSession); -- -- return session; -- } -- -- public PayloadType getPreferredPayloadType() { -- if (preferredPayloadType != null) -- return preferredPayloadType; -- return super.getPreferredPayloadType(); -- } -- -- public void setPreferredPayloadType(PayloadType preferredPayloadType) { -- this.preferredPayloadType = preferredPayloadType; -- } -- -- public String getName() { -- return MEDIA_NAME; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (working copy) -@@ -1,282 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl; -- --import java.awt.Frame; --import java.awt.TextArea; --import java.awt.Toolkit; --import java.util.Vector; -- --import javax.media.Format; --import javax.media.PlugInManager; --import javax.media.Renderer; --import javax.media.format.AudioFormat; -- --import org.jivesoftware.smackx.jingle.SmackLogger; -- --import com.sun.media.ExclusiveUse; --import com.sun.media.util.Registry; -- --public class JMFInit extends Frame implements Runnable { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class); -- -- private String tempDir = "/tmp"; -- -- private boolean done = false; -- -- private String userHome; -- -- private boolean visible = false; -- -- public JMFInit(String[] args, boolean visible) { -- super("Initializing JMF..."); -- -- this.visible = visible; -- -- Registry.set("secure.allowCaptureFromApplets", true); -- Registry.set("secure.allowSaveFileFromApplets", true); -- -- updateTemp(args); -- -- try { -- Registry.commit(); -- } -- catch (Exception e) { -- -- message("Failed to commit to JMFRegistry!"); -- } -- -- Thread detectThread = new Thread(this); -- detectThread.run(); -- -- /* -- * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try { -- * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { } -- * slept += 500; } -- * -- * if (!done) { console.error("Detection is taking too long! -- * Aborting!"); message("Detection is taking too long! Aborting!"); } -- * -- * try { Thread.currentThread().sleep(2000); } catch -- * (InterruptedException ie) { } -- */ -- } -- -- public void run() { -- detectDirectAudio(); -- detectS8DirectAudio(); -- detectCaptureDevices(); -- done = true; -- } -- -- private void updateTemp(String[] args) { -- if (args != null && args.length > 0) { -- tempDir = args[0]; -- -- message("Setting cache directory to " + tempDir); -- Registry r = new Registry(); -- try { -- r.set("secure.cacheDir", tempDir); -- r.commit(); -- -- message("Updated registry"); -- } -- catch (Exception e) { -- message("Couldn't update registry!"); -- } -- } -- } -- -- private void detectCaptureDevices() { -- // check if JavaSound capture is available -- message("Looking for Audio capturer"); -- Class dsauto; -- try { -- dsauto = Class.forName("DirectSoundAuto"); -- dsauto.newInstance(); -- message("Finished detecting DirectSound capturer"); -- } -- catch (ThreadDeath td) { -- throw td; -- } -- catch (Throwable t) { -- //Do nothing -- } -- -- Class jsauto; -- try { -- jsauto = Class.forName("JavaSoundAuto"); -- jsauto.newInstance(); -- message("Finished detecting javasound capturer"); -- } -- catch (ThreadDeath td) { -- throw td; -- } -- catch (Throwable t) { -- message("JavaSound capturer detection failed!"); -- } -- -- /* -- // Check if VFWAuto or SunVideoAuto is available -- message("Looking for video capture devices"); -- Class auto = null; -- Class autoPlus = null; -- try { -- auto = Class.forName("VFWAuto"); -- } -- catch (Exception e) { -- } -- if (auto == null) { -- try { -- auto = Class.forName("SunVideoAuto"); -- } -- catch (Exception ee) { -- -- } -- try { -- autoPlus = Class.forName("SunVideoPlusAuto"); -- } -- catch (Exception ee) { -- -- } -- } -- if (auto == null) { -- try { -- auto = Class.forName("V4LAuto"); -- } -- catch (Exception ee) { -- -- } -- } -- try { -- Object instance = auto.newInstance(); -- if (autoPlus != null) { -- Object instancePlus = autoPlus.newInstance(); -- } -- -- message("Finished detecting video capture devices"); -- } -- catch (ThreadDeath td) { -- throw td; -- } -- catch (Throwable t) { -- -- message("Capture device detection failed!"); -- } -- */ -- } -- -- private void detectDirectAudio() { -- Class cls; -- int plType = PlugInManager.RENDERER; -- String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; -- try { -- // Check if this is the Windows Performance Pack - hack -- cls = Class.forName("VFWAuto"); -- // Check if DS capture is supported, otherwise fail DS renderer -- // since NT doesn't have capture -- cls = Class.forName("com.sun.media.protocol.dsound.DSound"); -- // Find the renderer class and instantiate it. -- cls = Class.forName(dar); -- -- Renderer rend = (Renderer) cls.newInstance(); -- try { -- // Set the format and open the device -- AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16, -- 2); -- rend.setInputFormat(af); -- rend.open(); -- Format[] inputFormats = rend.getSupportedInputFormats(); -- // Register the device -- PlugInManager.addPlugIn(dar, inputFormats, new Format[0], -- plType); -- // Move it to the top of the list -- Vector rendList = PlugInManager.getPlugInList(null, null, -- plType); -- int listSize = rendList.size(); -- if (rendList.elementAt(listSize - 1).equals(dar)) { -- rendList.removeElementAt(listSize - 1); -- rendList.insertElementAt(dar, 0); -- PlugInManager.setPlugInList(rendList, plType); -- PlugInManager.commit(); -- // Log.debug("registered"); -- } -- rend.close(); -- } -- catch (Throwable t) { -- // Log.debug("Error " + t); -- } -- } -- catch (Throwable tt) { -- //Do nothing -- } -- } -- -- private void detectS8DirectAudio() { -- Class cls; -- int plType = PlugInManager.RENDERER; -- String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; -- try { -- // Check if this is the solaris Performance Pack - hack -- cls = Class.forName("SunVideoAuto"); -- -- // Find the renderer class and instantiate it. -- cls = Class.forName(dar); -- -- Renderer rend = (Renderer) cls.newInstance(); -- -- if (rend instanceof ExclusiveUse -- && !((ExclusiveUse) rend).isExclusive()) { -- // sol8+, DAR supports mixing -- Vector rendList = PlugInManager.getPlugInList(null, null, -- plType); -- int listSize = rendList.size(); -- boolean found = false; -- String rname = null; -- -- for (int i = 0; i < listSize; i++) { -- rname = (String) (rendList.elementAt(i)); -- if (rname.equals(dar)) { // DAR is in the registry -- found = true; -- rendList.removeElementAt(i); -- break; -- } -- } -- -- if (found) { -- rendList.insertElementAt(dar, 0); -- PlugInManager.setPlugInList(rendList, plType); -- PlugInManager.commit(); -- } -- } -- } -- catch (Throwable tt) { -- //Do nothing -- } -- } -- -- private void message(String mesg) { -- LOGGER.debug(mesg); -- } -- -- private void createGUI() { -- TextArea textBox = new TextArea(5, 50); -- add("Center", textBox); -- textBox.setEditable(false); -- addNotify(); -- pack(); -- -- int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize() -- .getWidth(); -- int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize() -- .getHeight(); -- -- setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2); -- -- setVisible(visible); -- -- } -- -- public static void start(boolean visible) { -- new JMFInit(null, visible); -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (working copy) -@@ -1,174 +0,0 @@ --/** -- * $RCSfile: Demo.java,v $ -- * $Revision: 1.3 $ -- * $Date: 28/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.demo; -- --import org.jivesoftware.smack.Connection; --import org.jivesoftware.smack.XMPPConnection; --import org.jivesoftware.smack.XMPPException; --import org.jivesoftware.smackx.jingle.JingleManager; --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.JingleSessionRequest; --import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener; --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager; --import org.jivesoftware.smackx.jingle.nat.ICETransportManager; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; -- --import javax.swing.*; --import java.awt.event.ActionEvent; --import java.util.ArrayList; --import java.util.List; -- --/** -- * Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls. -- * Parameters: Server User Pass. -- */ --public class Demo extends JFrame { -- -- private JingleTransportManager transportManager = null; -- private Connection xmppConnection = null; -- -- private String server = null; -- private String user = null; -- private String pass = null; -- -- private JingleManager jm = null; -- private JingleSession incoming = null; -- private JingleSession outgoing = null; -- -- private JTextField jid; -- -- public Demo(String server, String user, String pass) { -- -- this.server = server; -- this.user = user; -- this.pass = pass; -- -- if (user.equals("jeffw")) { -- jid = new JTextField("eowyn" + "@" + server + "/Smack"); -- } else { -- jid = new JTextField("jeffw" + "@" + server + "/Smack"); -- } -- -- xmppConnection = new XMPPConnection(server); -- try { -- xmppConnection.connect(); -- xmppConnection.login(user, pass); -- initialize(); -- } -- catch (XMPPException e) { -- e.printStackTrace(); -- } -- } -- -- public void initialize() { -- ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478); -- List mediaManagers = new ArrayList(); -- //mediaManagers.add(new JmfMediaManager(icetm0)); -- mediaManagers.add(new SpeexMediaManager(icetm0)); -- mediaManagers.add(new ScreenShareMediaManager(icetm0)); -- jm = new JingleManager(xmppConnection, mediaManagers); -- jm.addCreationListener(icetm0); -- -- jm.addJingleSessionRequestListener(new JingleSessionRequestListener() { -- public void sessionRequested(JingleSessionRequest request) { -- --// if (incoming != null) --// return; -- -- try { -- // Accept the call -- incoming = request.accept(); -- -- // Start the call -- incoming.startIncoming(); -- } -- catch (XMPPException e) { -- e.printStackTrace(); -- } -- -- } -- }); -- createGUI(); -- } -- -- public void createGUI() { -- -- JPanel jPanel = new JPanel(); -- -- jPanel.add(jid); -- -- jPanel.add(new JButton(new AbstractAction("Call") { -- public void actionPerformed(ActionEvent e) { -- if (outgoing != null) return; -- try { -- outgoing = jm.createOutgoingJingleSession(jid.getText()); -- outgoing.startOutgoing(); -- } -- catch (XMPPException e1) { -- e1.printStackTrace(); -- } -- } -- })); -- -- jPanel.add(new JButton(new AbstractAction("Hangup") { -- public void actionPerformed(ActionEvent e) { -- if (outgoing != null) -- try { -- outgoing.terminate(); -- } -- catch (XMPPException e1) { -- e1.printStackTrace(); -- } -- finally { -- outgoing = null; -- } -- if (incoming != null) -- try { -- incoming.terminate(); -- } -- catch (XMPPException e1) { -- e1.printStackTrace(); -- } -- finally { -- incoming = null; -- } -- } -- })); -- -- this.add(jPanel); -- -- } -- -- public static void main(String args[]) { -- -- Demo demo = null; -- -- if (args.length > 2) { -- demo = new Demo(args[0], args[1], args[2]); -- demo.pack(); -- demo.setVisible(true); -- demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); -- } -- -- } -- --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (working copy) -@@ -1,206 +0,0 @@ --/** -- * $RCSfile: ScreenShareSession.java,v $ -- * $Revision: 1.2 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.sshare; -- --import java.awt.Rectangle; --import java.awt.event.WindowAdapter; --import java.awt.event.WindowEvent; --import java.io.IOException; --import java.net.DatagramSocket; --import java.net.InetAddress; --import java.net.ServerSocket; --import java.net.UnknownHostException; -- --import javax.swing.JFrame; --import javax.swing.JPanel; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageReceiver; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * This Class implements a complete JingleMediaSession. -- * It sould be used to transmit and receive captured images from the Display. -- * This Class should be automaticly controlled by JingleSession. -- * For better NAT Traversal support this implementation don't support only receive or only transmit. -- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() -- * -- * @author Thiago Camargo -- */ --public class ScreenShareSession extends JingleMediaSession { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(ScreenShareSession.class); -- -- private ImageTransmitter transmitter = null; -- private ImageReceiver receiver = null; -- private int width = 600; -- private int height = 600; -- -- /** -- * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates -- * -- * @param payloadType Payload of the jmf -- * @param remote the remote information. The candidate that the jmf will be sent to. -- * @param local the local information. The candidate that will receive the jmf -- * @param locator media locator -- */ -- public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, -- final String locator, JingleSession jingleSession) { -- super(payloadType, remote, local, "Screen", jingleSession); -- initialize(); -- } -- -- /** -- * Initialize the screen share channels. -- */ -- public void initialize() { -- -- JingleSession session = getJingleSession(); -- if ((session != null) && (session.getInitiator().equals(session.getConnection().getUser()))) { -- // If the initiator of the jingle session is us then we transmit a screen share. -- try { -- InetAddress remote = InetAddress.getByName(getRemote().getIp()); -- transmitter = new ImageTransmitter(new DatagramSocket(getLocal().getPort()), remote, getRemote().getPort(), -- new Rectangle(0, 0, width, height)); -- } catch (Exception e) { -- e.printStackTrace(); -- } -- -- } else { -- // Otherwise we receive a screen share. -- JFrame window = new JFrame(); -- JPanel jp = new JPanel(); -- window.add(jp); -- -- window.setLocation(0, 0); -- window.setSize(600, 600); -- -- window.addWindowListener(new WindowAdapter() { -- public void windowClosed(WindowEvent e) { -- receiver.stop(); -- } -- }); -- -- try { -- receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width, -- height); -- LOGGER.debug("Receiving on:" + receiver.getLocalPort()); -- } catch (UnknownHostException e) { -- e.printStackTrace(); -- } -- -- jp.add(receiver); -- receiver.setVisible(true); -- window.setAlwaysOnTop(true); -- window.setVisible(true); -- } -- } -- -- /** -- * Starts transmission and for NAT Traversal reasons start receiving also. -- */ -- public void startTrasmit() { -- new Thread(transmitter).start(); -- } -- -- /** -- * Set transmit activity. If the active is true, the instance should trasmit. -- * If it is set to false, the instance should pause transmit. -- * -- * @param active active state -- */ -- public void setTrasmit(boolean active) { -- transmitter.setTransmit(true); -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void startReceive() { -- // Do nothing -- } -- -- /** -- * Stops transmission and for NAT Traversal reasons stop receiving also. -- */ -- public void stopTrasmit() { -- if (transmitter != null) { -- transmitter.stop(); -- } -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void stopReceive() { -- if (receiver != null) { -- receiver.stop(); -- } -- } -- -- /** -- * Obtain a free port we can use. -- * -- * @return A free port number. -- */ -- protected int getFreePort() { -- ServerSocket ss; -- int freePort = 0; -- -- for (int i = 0; i < 10; i++) { -- freePort = (int) (10000 + Math.round(Math.random() * 10000)); -- freePort = freePort % 2 == 0 ? freePort : freePort + 1; -- try { -- ss = new ServerSocket(freePort); -- freePort = ss.getLocalPort(); -- ss.close(); -- return freePort; -- } catch (IOException e) { -- e.printStackTrace(); -- } -- } -- try { -- ss = new ServerSocket(0); -- freePort = ss.getLocalPort(); -- ss.close(); -- } catch (IOException e) { -- e.printStackTrace(); -- } -- return freePort; -- } -- -- public void setEncoder(ImageEncoder encoder) { -- if (encoder != null) { -- this.transmitter.setEncoder(encoder); -- } -- } -- -- public void setDecoder(ImageDecoder decoder) { -- if (decoder != null) { -- this.receiver.setDecoder(decoder); -- } -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (working copy) -@@ -1,204 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.AWTException; --import java.awt.Rectangle; --import java.awt.Robot; --import java.awt.image.BufferedImage; --import java.awt.image.PixelGrabber; --import java.io.ByteArrayOutputStream; --import java.io.IOException; --import java.net.DatagramPacket; --import java.net.DatagramSocket; --import java.net.InetAddress; --import java.util.Arrays; -- --import org.jivesoftware.smackx.jingle.SmackLogger; -- --/** -- * UDP Image Receiver. -- * It uses PNG Tiles into UDP packets. -- * -- * @author Thiago Rocha Camargo -- */ --public class ImageTransmitter implements Runnable { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class); -- -- private Robot robot; -- private InetAddress localHost; -- private InetAddress remoteHost; -- private int localPort; -- private int remotePort; -- public static final int tileWidth = 25; -- private boolean on = true; -- private boolean transmit = false; -- private DatagramSocket socket; -- private Rectangle area; -- private int tiles[][][]; -- private int maxI; -- private int maxJ; -- private ImageEncoder encoder; -- public final static int KEYFRAME = 10; -- -- public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) { -- -- try { -- robot = new Robot(); -- -- maxI = (int) Math.ceil(area.getWidth() / tileWidth); -- maxJ = (int) Math.ceil(area.getHeight() / tileWidth); -- -- tiles = new int[maxI][maxJ][tileWidth * tileWidth]; -- -- this.area = area; -- this.socket = socket; -- localHost = socket.getLocalAddress(); -- localPort = socket.getLocalPort(); -- this.remoteHost = remoteHost; -- this.remotePort = remotePort; -- this.encoder = new DefaultEncoder(); -- -- transmit = true; -- -- } -- catch (AWTException e) { -- e.printStackTrace(); -- } -- -- } -- -- public void start() { -- byte buf[] = new byte[1024]; -- final DatagramPacket p = new DatagramPacket(buf, 1024); -- -- int keyframe = 0; -- -- while (on) { -- if (transmit) { -- -- BufferedImage capture = robot.createScreenCapture(area); -- -- QuantizeFilter filter = new QuantizeFilter(); -- capture = filter.filter(capture, null); -- -- long trace = System.currentTimeMillis(); -- -- if (++keyframe > KEYFRAME) { -- keyframe = 0; -- } -- LOGGER.debug("KEYFRAME:" + keyframe); -- -- for (int i = 0; i < maxI; i++) { -- for (int j = 0; j < maxJ; j++) { -- -- final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth); -- -- int pixels[] = new int[tileWidth * tileWidth]; -- -- PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth); -- -- try { -- if (pg.grabPixels()) { -- -- if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) { -- -- ByteArrayOutputStream baos = encoder.encode(bufferedImage); -- -- if (baos != null) { -- -- try { -- -- Thread.sleep(1); -- -- baos.write(i); -- baos.write(j); -- -- byte[] bytesOut = baos.toByteArray(); -- -- if (bytesOut.length > 1000) -- LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length); -- -- p.setData(bytesOut); -- p.setAddress(remoteHost); -- p.setPort(remotePort); -- -- try { -- socket.send(p); -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- -- tiles[i][j] = pixels; -- -- } -- catch (Exception e) { -- } -- -- } -- -- } -- -- } -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- } -- } -- -- trace = (System.currentTimeMillis() - trace); -- LOGGER.debug("Loop Time:" + trace); -- -- if (trace < 500) { -- try { -- Thread.sleep(500 - trace); -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- } -- } -- } -- } -- -- public void run() { -- start(); -- } -- -- /** -- * Set Transmit Enabled/Disabled -- * -- * @param transmit boolean Enabled/Disabled -- */ -- public void setTransmit(boolean transmit) { -- this.transmit = transmit; -- } -- -- /** -- * Get the encoder used to encode Images Tiles -- * -- * @return encoder -- */ -- public ImageEncoder getEncoder() { -- return encoder; -- } -- -- /** -- * Set the encoder used to encode Image Tiles -- * -- * @param encoder encoder -- */ -- public void setEncoder(ImageEncoder encoder) { -- this.encoder = encoder; -- } -- -- /** -- * Stops Transmitter -- */ -- public void stop() { -- this.transmit = false; -- this.on = false; -- socket.close(); -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (working copy) -@@ -1,13 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.image.BufferedImage; --import java.io.ByteArrayOutputStream; -- --/** -- * Image Encoder Interface use this interface if you want to change the default encoder -- * -- * @author Thiago Rocha Camargo -- */ --public interface ImageEncoder { -- public ByteArrayOutputStream encode(BufferedImage bufferedImage); --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (working copy) -@@ -1,223 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.*; --import java.util.Random; -- --/** -- * Some more useful math functions for image processing. -- * These are becoming obsolete as we move to Java2D. Use MiscComposite instead. -- */ --public class PixelUtils { -- -- public final static int REPLACE = 0; -- public final static int NORMAL = 1; -- public final static int MIN = 2; -- public final static int MAX = 3; -- public final static int ADD = 4; -- public final static int SUBTRACT = 5; -- public final static int DIFFERENCE = 6; -- public final static int MULTIPLY = 7; -- public final static int HUE = 8; -- public final static int SATURATION = 9; -- public final static int VALUE = 10; -- public final static int COLOR = 11; -- public final static int SCREEN = 12; -- public final static int AVERAGE = 13; -- public final static int OVERLAY = 14; -- public final static int CLEAR = 15; -- public final static int EXCHANGE = 16; -- public final static int DISSOLVE = 17; -- public final static int DST_IN = 18; -- public final static int ALPHA = 19; -- public final static int ALPHA_TO_GRAY = 20; -- -- private static Random randomGenerator = new Random(); -- -- /** -- * Clamp a value to the range 0..255 -- */ -- public static int clamp(int c) { -- if (c < 0) -- return 0; -- if (c > 255) -- return 255; -- return c; -- } -- -- public static int interpolate(int v1, int v2, float f) { -- return clamp((int)(v1+f*(v2-v1))); -- } -- -- public static int brightness(int rgb) { -- int r = (rgb >> 16) & 0xff; -- int g = (rgb >> 8) & 0xff; -- int b = rgb & 0xff; -- return (r+g+b)/3; -- } -- -- public static boolean nearColors(int rgb1, int rgb2, int tolerance) { -- int r1 = (rgb1 >> 16) & 0xff; -- int g1 = (rgb1 >> 8) & 0xff; -- int b1 = rgb1 & 0xff; -- int r2 = (rgb2 >> 16) & 0xff; -- int g2 = (rgb2 >> 8) & 0xff; -- int b2 = rgb2 & 0xff; -- return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; -- } -- -- private final static float hsb1[] = new float[3];//FIXME-not thread safe -- private final static float hsb2[] = new float[3];//FIXME-not thread safe -- -- // Return rgb1 painted onto rgb2 -- public static int combinePixels(int rgb1, int rgb2, int op) { -- return combinePixels(rgb1, rgb2, op, 0xff); -- } -- -- public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { -- return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); -- } -- -- public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { -- if (op == REPLACE) -- return rgb1; -- int a1 = (rgb1 >> 24) & 0xff; -- int r1 = (rgb1 >> 16) & 0xff; -- int g1 = (rgb1 >> 8) & 0xff; -- int b1 = rgb1 & 0xff; -- int a2 = (rgb2 >> 24) & 0xff; -- int r2 = (rgb2 >> 16) & 0xff; -- int g2 = (rgb2 >> 8) & 0xff; -- int b2 = rgb2 & 0xff; -- -- switch (op) { -- case NORMAL: -- break; -- case MIN: -- r1 = Math.min(r1, r2); -- g1 = Math.min(g1, g2); -- b1 = Math.min(b1, b2); -- break; -- case MAX: -- r1 = Math.max(r1, r2); -- g1 = Math.max(g1, g2); -- b1 = Math.max(b1, b2); -- break; -- case ADD: -- r1 = clamp(r1+r2); -- g1 = clamp(g1+g2); -- b1 = clamp(b1+b2); -- break; -- case SUBTRACT: -- r1 = clamp(r2-r1); -- g1 = clamp(g2-g1); -- b1 = clamp(b2-b1); -- break; -- case DIFFERENCE: -- r1 = clamp(Math.abs(r1-r2)); -- g1 = clamp(Math.abs(g1-g2)); -- b1 = clamp(Math.abs(b1-b2)); -- break; -- case MULTIPLY: -- r1 = clamp(r1*r2/255); -- g1 = clamp(g1*g2/255); -- b1 = clamp(b1*b2/255); -- break; -- case DISSOLVE: -- if ((randomGenerator.nextInt() & 0xff) <= a1) { -- r1 = r2; -- g1 = g2; -- b1 = b2; -- } -- break; -- case AVERAGE: -- r1 = (r1+r2)/2; -- g1 = (g1+g2)/2; -- b1 = (b1+b2)/2; -- break; -- case HUE: -- case SATURATION: -- case VALUE: -- case COLOR: -- Color.RGBtoHSB(r1, g1, b1, hsb1); -- Color.RGBtoHSB(r2, g2, b2, hsb2); -- switch (op) { -- case HUE: -- hsb2[0] = hsb1[0]; -- break; -- case SATURATION: -- hsb2[1] = hsb1[1]; -- break; -- case VALUE: -- hsb2[2] = hsb1[2]; -- break; -- case COLOR: -- hsb2[0] = hsb1[0]; -- hsb2[1] = hsb1[1]; -- break; -- } -- rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); -- r1 = (rgb1 >> 16) & 0xff; -- g1 = (rgb1 >> 8) & 0xff; -- b1 = rgb1 & 0xff; -- break; -- case SCREEN: -- r1 = 255 - ((255 - r1) * (255 - r2)) / 255; -- g1 = 255 - ((255 - g1) * (255 - g2)) / 255; -- b1 = 255 - ((255 - b1) * (255 - b2)) / 255; -- break; -- case OVERLAY: -- int m, s; -- s = 255 - ((255 - r1) * (255 - r2)) / 255; -- m = r1 * r2 / 255; -- r1 = (s * r1 + m * (255 - r1)) / 255; -- s = 255 - ((255 - g1) * (255 - g2)) / 255; -- m = g1 * g2 / 255; -- g1 = (s * g1 + m * (255 - g1)) / 255; -- s = 255 - ((255 - b1) * (255 - b2)) / 255; -- m = b1 * b2 / 255; -- b1 = (s * b1 + m * (255 - b1)) / 255; -- break; -- case CLEAR: -- r1 = g1 = b1 = 0xff; -- break; -- case DST_IN: -- r1 = clamp((r2*a1)/255); -- g1 = clamp((g2*a1)/255); -- b1 = clamp((b2*a1)/255); -- a1 = clamp((a2*a1)/255); -- return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; -- case ALPHA: -- a1 = a1*a2/255; -- return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; -- case ALPHA_TO_GRAY: -- int na = 255-a1; -- return (a1 << 24) | (na << 16) | (na << 8) | na; -- } -- if (extraAlpha != 0xff || a1 != 0xff) { -- a1 = a1*extraAlpha/255; -- int a3 = (255-a1)*a2/255; -- r1 = clamp((r1*a1+r2*a3)/255); -- g1 = clamp((g1*a1+g2*a3)/255); -- b1 = clamp((b1*a1+b2*a3)/255); -- a1 = clamp(a1+a3); -- } -- return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; -- } -- --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (working copy) -@@ -1,53 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --/** -- * The interface for an image quantizer. The addColor method is called (repeatedly -- * if necessary) with all the image pixels. A color table can then be returned by -- * calling the buildColorTable method. -- */ --public interface Quantizer { -- /** -- * Initialize the quantizer. This should be called before adding any pixels. -- * @param numColors the number of colors we're quantizing to. -- */ -- public void setup(int numColors); -- -- /** -- * Add pixels to the quantizer. -- * @param pixels the array of ARGB pixels -- * @param offset the offset into the array -- * @param count the count of pixels -- */ -- public void addPixels(int[] pixels, int offset, int count); -- -- /** -- * Build a color table from the added pixels. -- * @return an array of ARGB pixels representing a color table -- */ -- public int[] buildColorTable(); -- -- /** -- * Using the previously-built color table, return the index into that table for a pixel. -- * This is guaranteed to return a valid index - returning the index of a color closer -- * to that requested if necessary. -- * @param rgb the pixel to find -- * @return the pixel's index in the color table -- */ -- public int getIndexForColor(int rgb); --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (working copy) -@@ -1,24 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import javax.imageio.ImageIO; --import java.awt.image.BufferedImage; --import java.io.ByteArrayOutputStream; --import java.io.IOException; -- --/** -- * Implements a default PNG Encoder -- */ --public class DefaultEncoder implements ImageEncoder{ -- -- public ByteArrayOutputStream encode(BufferedImage bufferedImage) { -- ByteArrayOutputStream baos = new ByteArrayOutputStream(); -- try { -- ImageIO.write(bufferedImage, "png", baos); -- } -- catch (IOException e) { -- e.printStackTrace(); -- baos = null; -- } -- return baos; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (working copy) -@@ -1,178 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.*; -- --/** -- * A filter which quantizes an image to a set number of colors - useful for producing -- * images which are to be encoded using an index color model. The filter can perform -- * Floyd-Steinberg error-diffusion dithering if required. At present, the quantization -- * is done using an octtree algorithm but I eventually hope to add more quantization -- * methods such as median cut. Note: at present, the filter produces an image which -- * uses the RGB color model (because the application it was written for required it). -- * I hope to extend it to produce an IndexColorModel by request. -- */ --public class QuantizeFilter extends WholeImageFilter { -- -- /** -- * Floyd-Steinberg dithering matrix. -- */ -- protected final static int[] matrix = { -- 0, 0, 0, -- 0, 0, 7, -- 3, 5, 1, -- }; -- private int sum = 3+5+7+1; -- -- private boolean dither; -- private int numColors = 256; -- private boolean serpentine = true; -- -- /** -- * Set the number of colors to quantize to. -- * @param numColors the number of colors. The default is 256. -- */ -- public void setNumColors(int numColors) { -- this.numColors = Math.min(Math.max(numColors, 8), 256); -- } -- -- /** -- * Get the number of colors to quantize to. -- * @return the number of colors. -- */ -- public int getNumColors() { -- return numColors; -- } -- -- /** -- * Set whether to use dithering or not. If not, the image is posterized. -- * @param dither true to use dithering -- */ -- public void setDither(boolean dither) { -- this.dither = dither; -- } -- -- /** -- * Return the dithering setting -- * @return the current setting -- */ -- public boolean getDither() { -- return dither; -- } -- -- /** -- * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output. -- * @param serpentine true to use serpentine pattern -- */ -- public void setSerpentine(boolean serpentine) { -- this.serpentine = serpentine; -- } -- -- /** -- * Return the serpentine setting -- * @return the current setting -- */ -- public boolean getSerpentine() { -- return serpentine; -- } -- -- public void quantize(int[] inPixels, int[] outPixels, int width, int height, int numColors, boolean dither, boolean serpentine) { -- int count = width*height; -- Quantizer quantizer = new OctTreeQuantizer(); -- quantizer.setup(numColors); -- quantizer.addPixels(inPixels, 0, count); -- int[] table = quantizer.buildColorTable(); -- -- if (!dither) { -- for (int i = 0; i < count; i++) -- outPixels[i] = table[quantizer.getIndexForColor(inPixels[i])]; -- } else { -- int index = 0; -- for (int y = 0; y < height; y++) { -- boolean reverse = serpentine && (y & 1) == 1; -- int direction; -- if (reverse) { -- index = y*width+width-1; -- direction = -1; -- } else { -- index = y*width; -- direction = 1; -- } -- for (int x = 0; x < width; x++) { -- int rgb1 = inPixels[index]; -- int rgb2 = table[quantizer.getIndexForColor(rgb1)]; -- -- outPixels[index] = rgb2; -- -- int r1 = (rgb1 >> 16) & 0xff; -- int g1 = (rgb1 >> 8) & 0xff; -- int b1 = rgb1 & 0xff; -- -- int r2 = (rgb2 >> 16) & 0xff; -- int g2 = (rgb2 >> 8) & 0xff; -- int b2 = rgb2 & 0xff; -- -- int er = r1-r2; -- int eg = g1-g2; -- int eb = b1-b2; -- -- for (int i = -1; i <= 1; i++) { -- int iy = i+y; -- if (0 <= iy && iy < height) { -- for (int j = -1; j <= 1; j++) { -- int jx = j+x; -- if (0 <= jx && jx < width) { -- int w; -- if (reverse) -- w = matrix[(i+1)*3-j+1]; -- else -- w = matrix[(i+1)*3+j+1]; -- if (w != 0) { -- int k = reverse ? index - j : index + j; -- rgb1 = inPixels[k]; -- r1 = (rgb1 >> 16) & 0xff; -- g1 = (rgb1 >> 8) & 0xff; -- b1 = rgb1 & 0xff; -- r1 += er * w/sum; -- g1 += eg * w/sum; -- b1 += eb * w/sum; -- inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1); -- } -- } -- } -- } -- } -- index += direction; -- } -- } -- } -- } -- -- protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { -- int[] outPixels = new int[width*height]; -- -- quantize(inPixels, outPixels, width, height, numColors, dither, serpentine); -- -- return outPixels; -- } -- -- public String toString() { -- return "Colors/Quantize..."; -- } -- --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (working copy) -@@ -1,150 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.*; --import java.awt.image.BufferedImage; --import java.io.ByteArrayInputStream; --import java.io.IOException; --import java.net.DatagramPacket; --import java.net.DatagramSocket; --import java.net.InetAddress; --import java.net.SocketException; -- --/** -- * UDP Image Receiver. -- * It uses PNG Tiles into UDP packets. -- * -- * @author Thiago Rocha Camargo -- */ --public class ImageReceiver extends Canvas { -- -- private boolean on = true; -- private DatagramSocket socket; -- private BufferedImage tiles[][]; -- private static final int tileWidth = ImageTransmitter.tileWidth; -- private InetAddress localHost; -- private InetAddress remoteHost; -- private int localPort; -- private int remotePort; -- private ImageDecoder decoder; -- -- public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) { -- tiles = new BufferedImage[width][height]; -- -- try { -- -- socket = new DatagramSocket(localPort); -- localHost = socket.getLocalAddress(); -- this.remoteHost = remoteHost; -- this.remotePort = remotePort; -- this.localPort = localPort; -- this.decoder = new DefaultDecoder(); -- -- new Thread(new Runnable() { -- public void run() { -- byte buf[] = new byte[1024]; -- DatagramPacket p = new DatagramPacket(buf, 1024); -- try { -- while (on) { -- socket.receive(p); -- -- int length = p.getLength(); -- -- BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2)); -- -- if (bufferedImage != null) { -- -- int x = p.getData()[length - 2]; -- int y = p.getData()[length - 1]; -- -- drawTile(x, y, bufferedImage); -- -- } -- -- } -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- } -- }).start(); -- -- new Thread(new Runnable() { -- public void run() { -- byte buf[] = new byte[1024]; -- DatagramPacket p = new DatagramPacket(buf, 1024); -- try { -- while (on) { -- -- p.setAddress(remoteHost); -- p.setPort(remotePort); -- socket.send(p); -- -- try { -- Thread.sleep(1000); -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- -- } -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- } -- }).start(); -- -- } -- catch (SocketException e) { -- e.printStackTrace(); -- } -- this.setSize(width, height); -- } -- -- public InetAddress getLocalHost() { -- return localHost; -- } -- -- public InetAddress getRemoteHost() { -- return remoteHost; -- } -- -- public int getLocalPort() { -- return localPort; -- } -- -- public int getRemotePort() { -- return remotePort; -- } -- -- public DatagramSocket getDatagramSocket() { -- return socket; -- } -- -- public void drawTile(int x, int y, BufferedImage bufferedImage) { -- tiles[x][y] = bufferedImage; -- //repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth); -- this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this); -- } -- -- public void paint(Graphics g) { -- for (int i = 0; i < tiles.length; i++) { -- for (int j = 0; j < tiles[0].length; j++) { -- g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this); -- } -- } -- } -- -- public ImageDecoder getDecoder() { -- return decoder; -- } -- -- public void setDecoder(ImageDecoder decoder) { -- this.decoder = decoder; -- } -- -- public void stop(){ -- this.on=false; -- socket.close(); -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (working copy) -@@ -1,86 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.*; --import java.awt.image.BufferedImage; --import java.awt.image.ColorModel; --import java.awt.image.WritableRaster; -- --/** -- * A filter which acts as a superclass for filters which need to have the whole image in memory -- * to do their stuff. -- */ --public abstract class WholeImageFilter extends AbstractBufferedImageOp { -- -- /** -- * The output image bounds. -- */ -- protected Rectangle transformedSpace; -- -- /** -- * The input image bounds. -- */ -- protected Rectangle originalSpace; -- -- /** -- * Construct a WholeImageFilter. -- */ -- public WholeImageFilter() { -- } -- -- public BufferedImage filter( BufferedImage src, BufferedImage dst ) { -- int width = src.getWidth(); -- int height = src.getHeight(); -- int type = src.getType(); -- WritableRaster srcRaster = src.getRaster(); -- -- originalSpace = new Rectangle(0, 0, width, height); -- transformedSpace = new Rectangle(0, 0, width, height); -- transformSpace(transformedSpace); -- -- if ( dst == null ) { -- ColorModel dstCM = src.getColorModel(); -- dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null); -- } -- WritableRaster dstRaster = dst.getRaster(); -- -- int[] inPixels = getRGB( src, 0, 0, width, height, null ); -- inPixels = filterPixels( width, height, inPixels, transformedSpace ); -- setRGB( dst, 0, 0, transformedSpace.width, transformedSpace.height, inPixels ); -- -- return dst; -- } -- -- /** -- * Calculate output bounds for given input bounds. -- * @param rect input and output rectangle -- */ -- protected void transformSpace(Rectangle rect) { -- } -- -- /** -- * Actually filter the pixels. -- * @param width the image width -- * @param height the image height -- * @param inPixels the image pixels -- * @param transformedSpace the output bounds -- * @return the output pixels -- */ -- protected abstract int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ); --} -- -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (working copy) -@@ -1,98 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.*; --import java.awt.geom.Point2D; --import java.awt.geom.Rectangle2D; --import java.awt.image.BufferedImage; --import java.awt.image.BufferedImageOp; --import java.awt.image.ColorModel; -- --/** -- * A convenience class which implements those methods of BufferedImageOp which are rarely changed. -- */ --public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable { -- -- public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { -- if ( dstCM == null ) -- dstCM = src.getColorModel(); -- return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); -- } -- -- public Rectangle2D getBounds2D( BufferedImage src ) { -- return new Rectangle(0, 0, src.getWidth(), src.getHeight()); -- } -- -- public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { -- if ( dstPt == null ) -- dstPt = new Point2D.Double(); -- dstPt.setLocation( srcPt.getX(), srcPt.getY() ); -- return dstPt; -- } -- -- public RenderingHints getRenderingHints() { -- return null; -- } -- -- /** -- * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance -- * penalty of BufferedImage.getRGB unmanaging the image. -- * @param image a BufferedImage object -- * @param x the left edge of the pixel block -- * @param y the right edge of the pixel block -- * @param width the width of the pixel arry -- * @param height the height of the pixel arry -- * @param pixels the array to hold the returned pixels. May be null. -- * @return the pixels -- * @see #setRGB -- */ -- public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { -- int type = image.getType(); -- if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) -- return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); -- return image.getRGB( x, y, width, height, pixels, 0, width ); -- } -- -- /** -- * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance -- * penalty of BufferedImage.setRGB unmanaging the image. -- * @param image a BufferedImage object -- * @param x the left edge of the pixel block -- * @param y the right edge of the pixel block -- * @param width the width of the pixel arry -- * @param height the height of the pixel arry -- * @param pixels the array of pixels to set -- * @see #getRGB -- */ -- public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { -- int type = image.getType(); -- if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) -- image.getRaster().setDataElements( x, y, width, height, pixels ); -- else -- image.setRGB( x, y, width, height, pixels, 0, width ); -- } -- -- public Object clone() { -- try { -- return super.clone(); -- } -- catch ( CloneNotSupportedException e ) { -- return null; -- } -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (working copy) -@@ -1,15 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.awt.image.BufferedImage; --import java.io.ByteArrayInputStream; --import java.io.IOException; -- --/** -- * Image Decoder Interface use this interface if you want to change the default decoder -- * -- * @author Thiago Rocha Camargo -- */ --public interface ImageDecoder { -- -- public BufferedImage decode(ByteArrayInputStream stream) throws IOException; --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (working copy) -@@ -1,287 +0,0 @@ --/* --Copyright 2006 Jerry Huxtable -- --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 org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import java.io.PrintStream; --import java.util.Vector; -- --import org.jivesoftware.smackx.jingle.SmackLogger; -- --/** -- * An image Quantizer based on the Octree algorithm. This is a very basic implementation -- * at present and could be much improved by picking the nodes to reduce more carefully -- * (i.e. not completely at random) when I get the time. -- */ --public class OctTreeQuantizer implements Quantizer { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(OctTreeQuantizer.class); -- -- /** -- * The greatest depth the tree is allowed to reach -- */ -- final static int MAX_LEVEL = 5; -- -- /** -- * An Octtree node. -- */ -- class OctTreeNode { -- int children; -- int level; -- OctTreeNode parent; -- OctTreeNode leaf[] = new OctTreeNode[8]; -- boolean isLeaf; -- int count; -- int totalRed; -- int totalGreen; -- int totalBlue; -- int index; -- -- /** -- * A debugging method which prints the tree out. -- */ -- public void list(PrintStream s, int level) { -- String indentStr = ""; -- for (int i = 0; i < level; i++) -- indentStr += " "; -- if (count == 0) -- LOGGER.debug(indentStr + index + ": count=" + count); -- else -- LOGGER.debug(indentStr + index + ": count=" + count + " red=" + (totalRed/count) + " green=" + (totalGreen / count) + " blue=" + (totalBlue / count)); -- for (int i = 0; i < 8; i++) -- if (leaf[i] != null) -- leaf[i].list(s, level+2); -- } -- } -- -- private int nodes = 0; -- private OctTreeNode root; -- private int reduceColors; -- private int maximumColors; -- private int colors = 0; -- private Vector[] colorList; -- -- public OctTreeQuantizer() { -- setup(256); -- colorList = new Vector[MAX_LEVEL+1]; -- for (int i = 0; i < MAX_LEVEL+1; i++) -- colorList[i] = new Vector(); -- root = new OctTreeNode(); -- } -- -- /** -- * Initialize the quantizer. This should be called before adding any pixels. -- * @param numColors the number of colors we're quantizing to. -- */ -- public void setup(int numColors) { -- maximumColors = numColors; -- reduceColors = Math.max(512, numColors * 2); -- } -- -- /** -- * Add pixels to the quantizer. -- * @param pixels the array of ARGB pixels -- * @param offset the offset into the array -- * @param count the count of pixels -- */ -- public void addPixels(int[] pixels, int offset, int count) { -- for (int i = 0; i < count; i++) { -- insertColor(pixels[i+offset]); -- if (colors > reduceColors) -- reduceTree(reduceColors); -- } -- } -- -- /** -- * Get the color table index for a color. -- * @param rgb the color -- * @return the index -- */ -- public int getIndexForColor(int rgb) { -- int red = (rgb >> 16) & 0xff; -- int green = (rgb >> 8) & 0xff; -- int blue = rgb & 0xff; -- -- OctTreeNode node = root; -- -- for (int level = 0; level <= MAX_LEVEL; level++) { -- OctTreeNode child; -- int bit = 0x80 >> level; -- -- int index = 0; -- if ((red & bit) != 0) -- index += 4; -- if ((green & bit) != 0) -- index += 2; -- if ((blue & bit) != 0) -- index += 1; -- -- child = node.leaf[index]; -- -- if (child == null) -- return node.index; -- else if (child.isLeaf) -- return child.index; -- else -- node = child; -- } -- LOGGER.debug("getIndexForColor failed"); -- return 0; -- } -- -- private void insertColor(int rgb) { -- int red = (rgb >> 16) & 0xff; -- int green = (rgb >> 8) & 0xff; -- int blue = rgb & 0xff; -- -- OctTreeNode node = root; -- --// LOGGER.debug("insertColor="+Integer.toHexString(rgb)); -- for (int level = 0; level <= MAX_LEVEL; level++) { -- OctTreeNode child; -- int bit = 0x80 >> level; -- -- int index = 0; -- if ((red & bit) != 0) -- index += 4; -- if ((green & bit) != 0) -- index += 2; -- if ((blue & bit) != 0) -- index += 1; -- -- child = node.leaf[index]; -- -- if (child == null) { -- node.children++; -- -- child = new OctTreeNode(); -- child.parent = node; -- node.leaf[index] = child; -- node.isLeaf = false; -- nodes++; -- colorList[level].addElement(child); -- -- if (level == MAX_LEVEL) { -- child.isLeaf = true; -- child.count = 1; -- child.totalRed = red; -- child.totalGreen = green; -- child.totalBlue = blue; -- child.level = level; -- colors++; -- return; -- } -- -- node = child; -- } else if (child.isLeaf) { -- child.count++; -- child.totalRed += red; -- child.totalGreen += green; -- child.totalBlue += blue; -- return; -- } else -- node = child; -- } -- LOGGER.debug("insertColor failed"); -- } -- -- private void reduceTree(int numColors) { -- for (int level = MAX_LEVEL-1; level >= 0; level--) { -- Vector v = colorList[level]; -- if (v != null && v.size() > 0) { -- for (int j = 0; j < v.size(); j++) { -- OctTreeNode node = (OctTreeNode)v.elementAt(j); -- if (node.children > 0) { -- for (int i = 0; i < 8; i++) { -- OctTreeNode child = node.leaf[i]; -- if (child != null) { -- if (!child.isLeaf) -- LOGGER.debug("not a leaf!"); -- node.count += child.count; -- node.totalRed += child.totalRed; -- node.totalGreen += child.totalGreen; -- node.totalBlue += child.totalBlue; -- node.leaf[i] = null; -- node.children--; -- colors--; -- nodes--; -- colorList[level+1].removeElement(child); -- } -- } -- node.isLeaf = true; -- colors++; -- if (colors <= numColors) -- return; -- } -- } -- } -- } -- -- LOGGER.debug("Unable to reduce the OctTree"); -- } -- -- /** -- * Build the color table. -- * @return the color table -- */ -- public int[] buildColorTable() { -- int[] table = new int[colors]; -- buildColorTable(root, table, 0); -- return table; -- } -- -- /** -- * A quick way to use the quantizer. Just create a table the right size and pass in the pixels. -- * @param inPixels the input colors -- * @param table the output color table -- */ -- public void buildColorTable(int[] inPixels, int[] table) { -- int count = inPixels.length; -- maximumColors = table.length; -- for (int i = 0; i < count; i++) { -- insertColor(inPixels[i]); -- if (colors > reduceColors) -- reduceTree(reduceColors); -- } -- if (colors > maximumColors) -- reduceTree(maximumColors); -- buildColorTable(root, table, 0); -- } -- -- private int buildColorTable(OctTreeNode node, int[] table, int index) { -- if (colors > maximumColors) -- reduceTree(maximumColors); -- -- if (node.isLeaf) { -- int count = node.count; -- table[index] = 0xff000000 | -- ((node.totalRed/count) << 16) | -- ((node.totalGreen/count) << 8) | -- node.totalBlue/count; -- node.index = index++; -- } else { -- for (int i = 0; i < 8; i++) { -- if (node.leaf[i] != null) { -- node.index = index; -- index = buildColorTable(node.leaf[i], table, index); -- } -- } -- } -- return index; -- } -- --} -- -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (working copy) -@@ -1,16 +0,0 @@ --package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; -- --import javax.imageio.ImageIO; --import java.awt.image.BufferedImage; --import java.io.ByteArrayInputStream; --import java.io.IOException; -- --/** -- * Implements a default PNG decoder. -- */ --public class DefaultDecoder implements ImageDecoder { -- -- public BufferedImage decode(ByteArrayInputStream stream) throws IOException { -- return ImageIO.read(stream); -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (working copy) -@@ -1,115 +0,0 @@ --/** -- * $RCSfile: ScreenShareMediaManager.java,v $ -- * $Revision: 1.3 $ -- * $Date: 25/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.sshare; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder; --import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --import java.util.ArrayList; --import java.util.List; -- --/** -- * Implements a JingleMediaManager for ScreenSharing. -- * It currently uses an Audio payload Type. Which needs to be fixed in the next version. -- * -- * @author Thiago Camargo -- */ -- --public class ScreenShareMediaManager extends JingleMediaManager { -- -- public static final String MEDIA_NAME = "ScreenShare"; -- -- private List payloads = new ArrayList(); -- -- private ImageDecoder decoder = null; -- private ImageEncoder encoder = null; -- -- public ScreenShareMediaManager(JingleTransportManager transportManager) { -- super(transportManager); -- setupPayloads(); -- } -- -- /** -- * Setup API supported Payloads -- */ -- private void setupPayloads() { -- payloads.add(new PayloadType.Audio(30, "sshare")); -- } -- -- /** -- * Return all supported Payloads for this Manager. -- * -- * @return The Payload List -- */ -- public List getPayloads() { -- return payloads; -- } -- -- /** -- * Returns a new JingleMediaSession -- * -- * @param payloadType payloadType -- * @param remote remote Candidate -- * @param local local Candidate -- * @return JingleMediaSession JingleMediaSession -- */ -- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { -- ScreenShareSession session = null; -- session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession); -- if (encoder != null) { -- session.setEncoder(encoder); -- } -- if (decoder != null) { -- session.setDecoder(decoder); -- } -- return session; -- } -- -- public PayloadType getPreferredPayloadType() { -- return super.getPreferredPayloadType(); -- } -- -- public ImageDecoder getDecoder() { -- return decoder; -- } -- -- public void setDecoder(ImageDecoder decoder) { -- this.decoder = decoder; -- } -- -- public ImageEncoder getEncoder() { -- return encoder; -- } -- -- public void setEncoder(ImageEncoder encoder) { -- this.encoder = encoder; -- } -- -- public String getName() { -- return MEDIA_NAME; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (working copy) -@@ -1,106 +0,0 @@ --/** -- * $RCSfile: MultiMediaManager.java,v $ -- * $Revision: 1.3 $ -- * $Date: 25/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.multi; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --import java.util.ArrayList; --import java.util.List; -- --/** -- * Implements a MultiMediaManager using other JingleMediaManager implementations. -- * It supports every Codecs that JingleMediaManagers added has. -- * -- * @author Thiago Camargo -- */ -- --public class MultiMediaManager extends JingleMediaManager { -- -- public static final String MEDIA_NAME = "Multi"; -- -- private List managers = new ArrayList(); -- -- private PayloadType preferredPayloadType = null; -- -- public MultiMediaManager(JingleTransportManager transportManager) { -- super(transportManager); -- } -- -- public void addMediaManager(JingleMediaManager manager) { -- managers.add(manager); -- } -- -- public void removeMediaManager(JingleMediaManager manager) { -- managers.remove(manager); -- } -- -- /** -- * Return all supported Payloads for this Manager. -- * -- * @return The Payload List -- */ -- public List getPayloads() { -- List list = new ArrayList(); -- if (preferredPayloadType != null) list.add(preferredPayloadType); -- for (JingleMediaManager manager : managers) { -- for (PayloadType payloadType : manager.getPayloads()) { -- if (!list.contains(payloadType) && !payloadType.equals(preferredPayloadType)) -- list.add(payloadType); -- } -- } -- return list; -- } -- -- /** -- * Returns a new JingleMediaSession -- * -- * @param payloadType payloadType -- * @param remote remote Candidate -- * @param local local Candidate -- * @return JingleMediaSession JingleMediaSession -- */ -- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { -- for (JingleMediaManager manager : managers) { -- if (manager.getPayloads().contains(payloadType)) { -- return manager.createMediaSession(payloadType, remote, local, jingleSession); -- } -- } -- return null; -- } -- -- public PayloadType getPreferredPayloadType() { -- if (preferredPayloadType != null) return preferredPayloadType; -- return super.getPreferredPayloadType(); -- } -- -- public void setPreferredPayloadType(PayloadType preferredPayloadType) { -- this.preferredPayloadType = preferredPayloadType; -- } -- -- public String getName() { -- return MEDIA_NAME; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (working copy) -@@ -1,165 +0,0 @@ --/** -- * $RCSfile: AudioMediaSession.java,v $ -- * $Revision: 1.1 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jmf; -- --import java.io.IOException; --import java.net.ServerSocket; -- --import javax.media.MediaLocator; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * This Class implements a complete JingleMediaSession. -- * It sould be used to transmit and receive audio captured from the Mic. -- * This Class should be automaticly controlled by JingleSession. -- * But you could also use in any VOIP application. -- * For better NAT Traversal support this implementation don't support only receive or only transmit. -- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() -- * -- * @author Thiago Camargo -- */ --public class AudioMediaSession extends JingleMediaSession { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class); -- -- private AudioChannel audioChannel; -- -- /** -- * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates -- * -- * @param payloadType Payload of the jmf -- * @param remote the remote information. The candidate that the jmf will be sent to. -- * @param local the local information. The candidate that will receive the jmf -- * @param locator media locator -- */ -- public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, -- final TransportCandidate local, String locator, JingleSession jingleSession) { -- super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession); -- initialize(); -- } -- -- /** -- * Initialize the Audio Channel to make it able to send and receive audio -- */ -- public void initialize() { -- -- String ip; -- String localIp; -- int localPort; -- int remotePort; -- -- if (this.getLocal().getSymmetric() != null) { -- ip = this.getLocal().getIp(); -- localIp = this.getLocal().getLocalIp(); -- localPort = getFreePort(); -- remotePort = this.getLocal().getSymmetric().getPort(); -- -- LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); -- -- } -- else { -- ip = this.getRemote().getIp(); -- localIp = this.getLocal().getLocalIp(); -- localPort = this.getLocal().getPort(); -- remotePort = this.getRemote().getPort(); -- } -- -- audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this); -- } -- -- /** -- * Starts transmission and for NAT Traversal reasons start receiving also. -- */ -- public void startTrasmit() { -- audioChannel.start(); -- } -- -- /** -- * Set transmit activity. If the active is true, the instance should trasmit. -- * If it is set to false, the instance should pause transmit. -- * -- * @param active active state -- */ -- public void setTrasmit(boolean active) { -- audioChannel.setTrasmit(active); -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void startReceive() { -- // Do nothing -- } -- -- /** -- * Stops transmission and for NAT Traversal reasons stop receiving also. -- */ -- public void stopTrasmit() { -- if (audioChannel != null) -- audioChannel.stop(); -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void stopReceive() { -- // Do nothing -- } -- -- /** -- * Obtain a free port we can use. -- * -- * @return A free port number. -- */ -- protected int getFreePort() { -- ServerSocket ss; -- int freePort = 0; -- -- for (int i = 0; i < 10; i++) { -- freePort = (int) (10000 + Math.round(Math.random() * 10000)); -- freePort = freePort % 2 == 0 ? freePort : freePort + 1; -- try { -- ss = new ServerSocket(freePort); -- freePort = ss.getLocalPort(); -- ss.close(); -- return freePort; -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- } -- try { -- ss = new ServerSocket(0); -- freePort = ss.getLocalPort(); -- ss.close(); -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- return freePort; -- } -- --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (working copy) -@@ -1,171 +0,0 @@ --/** -- * $RCSfile: AudioReceiver.java,v $ -- * $Revision: 1.1 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jmf; -- --import javax.media.ControllerErrorEvent; --import javax.media.ControllerEvent; --import javax.media.ControllerListener; --import javax.media.Player; --import javax.media.RealizeCompleteEvent; --import javax.media.protocol.DataSource; --import javax.media.rtp.Participant; --import javax.media.rtp.RTPControl; --import javax.media.rtp.ReceiveStream; --import javax.media.rtp.ReceiveStreamListener; --import javax.media.rtp.SessionListener; --import javax.media.rtp.event.ByeEvent; --import javax.media.rtp.event.NewParticipantEvent; --import javax.media.rtp.event.NewReceiveStreamEvent; --import javax.media.rtp.event.ReceiveStreamEvent; --import javax.media.rtp.event.RemotePayloadChangeEvent; --import javax.media.rtp.event.SessionEvent; --import javax.media.rtp.event.StreamMappedEvent; -- --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; -- --/** -- * This class implements receive methods and listeners to be used in AudioChannel -- * -- * @author Thiago Camargo -- */ --public class AudioReceiver implements ReceiveStreamListener, SessionListener, -- ControllerListener { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class); -- -- boolean dataReceived = false; -- -- Object dataSync; -- JingleMediaSession jingleMediaSession; -- -- public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) { -- this.dataSync = dataSync; -- this.jingleMediaSession = jingleMediaSession; -- } -- -- /** -- * JingleSessionListener. -- */ -- public synchronized void update(SessionEvent evt) { -- if (evt instanceof NewParticipantEvent) { -- Participant p = ((NewParticipantEvent) evt).getParticipant(); -- LOGGER.error(" - A new participant had just joined: " + p.getCNAME()); -- } -- } -- -- /** -- * ReceiveStreamListener -- */ -- public synchronized void update(ReceiveStreamEvent evt) { -- -- Participant participant = evt.getParticipant(); // could be null. -- ReceiveStream stream = evt.getReceiveStream(); // could be null. -- -- if (evt instanceof RemotePayloadChangeEvent) { -- LOGGER.error(" - Received an RTP PayloadChangeEvent."); -- LOGGER.error("Sorry, cannot handle payload change."); -- -- } -- else if (evt instanceof NewReceiveStreamEvent) { -- -- try { -- stream = evt.getReceiveStream(); -- DataSource ds = stream.getDataSource(); -- -- // Find out the formats. -- RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl"); -- if (ctl != null) { -- LOGGER.error(" - Recevied new RTP stream: " + ctl.getFormat()); -- } -- else -- LOGGER.error(" - Recevied new RTP stream"); -- -- if (participant == null) -- LOGGER.error(" The sender of this stream had yet to be identified."); -- else { -- LOGGER.error(" The stream comes from: " + participant.getCNAME()); -- } -- -- // create a player by passing datasource to the Media Manager -- Player p = javax.media.Manager.createPlayer(ds); -- if (p == null) -- return; -- -- p.addControllerListener(this); -- p.realize(); -- jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : ""); -- -- // Notify intialize() that a new stream had arrived. -- synchronized (dataSync) { -- dataReceived = true; -- dataSync.notifyAll(); -- } -- -- } -- catch (Exception e) { -- LOGGER.error("NewReceiveStreamEvent exception " + e.getMessage()); -- return; -- } -- -- } -- else if (evt instanceof StreamMappedEvent) { -- -- if (stream != null && stream.getDataSource() != null) { -- DataSource ds = stream.getDataSource(); -- // Find out the formats. -- RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl"); -- LOGGER.error(" - The previously unidentified stream "); -- if (ctl != null) -- LOGGER.error(" " + ctl.getFormat()); -- LOGGER.error(" had now been identified as sent by: " + participant.getCNAME()); -- } -- } -- else if (evt instanceof ByeEvent) { -- -- LOGGER.error(" - Got \"bye\" from: " + participant.getCNAME()); -- -- } -- -- } -- -- /** -- * ControllerListener for the Players. -- */ -- public synchronized void controllerUpdate(ControllerEvent ce) { -- -- Player p = (Player) ce.getSourceController(); -- -- if (p == null) -- return; -- -- // Get this when the internal players are realized. -- if (ce instanceof RealizeCompleteEvent) { -- p.start(); -- } -- -- if (ce instanceof ControllerErrorEvent) { -- p.removeControllerListener(this); -- LOGGER.error("Receiver internal error: " + ce); -- } -- -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (working copy) -@@ -1,170 +0,0 @@ --/** -- * $RCSfile: JmfMediaManager.java,v $ -- * $Revision: 1.3 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jmf; -- --import java.io.File; --import java.io.IOException; --import java.util.ArrayList; --import java.util.List; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * Implements a jingleMediaManager using JMF based API. -- * It supports GSM and G723 codecs. -- * This API only currently works on windows and Mac. -- * -- * @author Thiago Camargo -- */ --public class JmfMediaManager extends JingleMediaManager { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class); -- -- public static final String MEDIA_NAME = "JMF"; -- -- -- private List payloads = new ArrayList(); -- private String mediaLocator = null; -- -- /** -- * Creates a Media Manager instance -- */ -- public JmfMediaManager(JingleTransportManager transportManager) { -- super(transportManager); -- setupPayloads(); -- } -- -- /** -- * Creates a Media Manager instance -- * -- * @param mediaLocator Media Locator -- */ -- public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) { -- super(transportManager); -- this.mediaLocator = mediaLocator; -- setupPayloads(); -- } -- -- /** -- * Returns a new jingleMediaSession -- * -- * @param payloadType payloadType -- * @param remote remote Candidate -- * @param local local Candidate -- * @return JingleMediaSession -- */ -- public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { -- return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession); -- } -- -- /** -- * Setup API supported Payloads -- */ -- private void setupPayloads() { -- payloads.add(new PayloadType.Audio(3, "gsm")); -- payloads.add(new PayloadType.Audio(4, "g723")); -- payloads.add(new PayloadType.Audio(0, "PCMU", 16000)); -- } -- -- /** -- * Return all supported Payloads for this Manager -- * -- * @return The Payload List -- */ -- public List getPayloads() { -- return payloads; -- } -- -- /** -- * Return the media locator or null if not defined -- * -- * @return media locator -- */ -- public String getMediaLocator() { -- return mediaLocator; -- } -- -- /** -- * Set the media locator -- * -- * @param mediaLocator media locator or null to use default -- */ -- public void setMediaLocator(String mediaLocator) { -- this.mediaLocator = mediaLocator; -- } -- -- /** -- * Runs JMFInit the first time the application is started so that capture -- * devices are properly detected and initialized by JMF. -- */ -- public static void setupJMF() { -- // .jmf is the place where we store the jmf.properties file used -- // by JMF. if the directory does not exist or it does not contain -- // a jmf.properties file. or if the jmf.properties file has 0 length -- // then this is the first time we're running and should continue to -- // with JMFInit -- String homeDir = System.getProperty("user.home"); -- File jmfDir = new File(homeDir, ".jmf"); -- String classpath = System.getProperty("java.class.path"); -- classpath += System.getProperty("path.separator") -- + jmfDir.getAbsolutePath(); -- System.setProperty("java.class.path", classpath); -- -- if (!jmfDir.exists()) -- jmfDir.mkdir(); -- -- File jmfProperties = new File(jmfDir, "jmf.properties"); -- -- if (!jmfProperties.exists()) { -- try { -- jmfProperties.createNewFile(); -- } -- catch (IOException ex) { -- LOGGER.debug("Failed to create jmf.properties"); -- ex.printStackTrace(); -- } -- } -- -- // if we're running on linux checkout that libjmutil.so is where it -- // should be and put it there. -- runLinuxPreInstall(); -- -- //if (jmfProperties.length() == 0) { -- new JMFInit(null, false); -- //} -- -- } -- -- private static void runLinuxPreInstall() { -- // @TODO Implement Linux Pre-Install -- } -- -- public String getName() { -- return MEDIA_NAME; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (working copy) -@@ -1,553 +0,0 @@ --/** -- * $RCSfile: AudioChannel.java,v $ -- * $Revision: 1.1 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jmf; -- --import java.io.IOException; --import java.net.InetAddress; --import java.net.UnknownHostException; --import java.util.ArrayList; --import java.util.List; -- --import javax.media.Codec; --import javax.media.Controller; --import javax.media.ControllerClosedEvent; --import javax.media.ControllerEvent; --import javax.media.ControllerListener; --import javax.media.Format; --import javax.media.MediaLocator; --import javax.media.NoProcessorException; --import javax.media.Processor; --import javax.media.UnsupportedPlugInException; --import javax.media.control.BufferControl; --import javax.media.control.PacketSizeControl; --import javax.media.control.TrackControl; --import javax.media.format.AudioFormat; --import javax.media.protocol.ContentDescriptor; --import javax.media.protocol.DataSource; --import javax.media.protocol.PushBufferDataSource; --import javax.media.protocol.PushBufferStream; --import javax.media.rtp.InvalidSessionAddressException; --import javax.media.rtp.RTPManager; --import javax.media.rtp.SendStream; --import javax.media.rtp.SessionAddress; -- --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; -- --/** -- * An Easy to use Audio Channel implemented using JMF. -- * It sends and receives jmf for and from desired IPs and ports. -- * Also has a rport Symetric behavior for better NAT Traversal. -- * It send data from a defined port and receive data in the same port, making NAT binds easier. -- *

-- * Send from portA to portB and receive from portB in portA. -- *

-- * Sending -- * portA ---> portB -- *

-- * Receiving -- * portB ---> portA -- *

-- * Transmit and Receive are interdependents. To receive you MUST trasmit. -- * -- * @author Thiago Camargo -- */ --public class AudioChannel { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioChannel.class); -- -- private MediaLocator locator; -- private String localIpAddress; -- private String remoteIpAddress; -- private int localPort; -- private int portBase; -- private Format format; -- -- private Processor processor = null; -- private RTPManager rtpMgrs[]; -- private DataSource dataOutput = null; -- private AudioReceiver audioReceiver; -- -- private List sendStreams = new ArrayList(); -- -- private JingleMediaSession jingleMediaSession; -- -- private boolean started = false; -- -- /** -- * Creates an Audio Channel for a desired jmf locator. For instance: new MediaLocator("dsound://") -- * -- * @param locator media locator -- * @param localIpAddress local IP address -- * @param remoteIpAddress remote IP address -- * @param localPort local port number -- * @param remotePort remote port number -- * @param format audio format -- */ -- public AudioChannel(MediaLocator locator, -- String localIpAddress, -- String remoteIpAddress, -- int localPort, -- int remotePort, -- Format format, JingleMediaSession jingleMediaSession) { -- -- this.locator = locator; -- this.localIpAddress = localIpAddress; -- this.remoteIpAddress = remoteIpAddress; -- this.localPort = localPort; -- this.portBase = remotePort; -- this.format = format; -- this.jingleMediaSession = jingleMediaSession; -- } -- -- /** -- * Starts the transmission. Returns null if transmission started ok. -- * Otherwise it returns a string with the reason why the setup failed. -- * Starts receive also. -- * -- * @return result description -- */ -- public synchronized String start() { -- if (started) return null; -- -- // Create a processor for the specified jmf locator -- String result = createProcessor(); -- if (result != null) { -- started = false; -- } -- -- // Create an RTP session to transmit the output of the -- // processor to the specified IP address and port no. -- result = createTransmitter(); -- if (result != null) { -- processor.close(); -- processor = null; -- started = false; -- } -- else { -- started = true; -- } -- -- // Start the transmission -- processor.start(); -- -- return null; -- } -- -- /** -- * Stops the transmission if already started. -- * Stops the receiver also. -- */ -- public void stop() { -- if (!started) return; -- synchronized (this) { -- try { -- started = false; -- if (processor != null) { -- processor.stop(); -- processor = null; -- -- for (RTPManager rtpMgr : rtpMgrs) { -- rtpMgr.removeReceiveStreamListener(audioReceiver); -- rtpMgr.removeSessionListener(audioReceiver); -- rtpMgr.removeTargets("Session ended."); -- rtpMgr.dispose(); -- } -- -- sendStreams.clear(); -- -- } -- } -- catch (Exception e) { -- e.printStackTrace(); -- } -- } -- } -- -- private String createProcessor() { -- if (locator == null) -- return "Locator is null"; -- -- DataSource ds; -- -- try { -- ds = javax.media.Manager.createDataSource(locator); -- } -- catch (Exception e) { -- // Try JavaSound Locator as a last resort -- try { -- ds = javax.media.Manager.createDataSource(new MediaLocator("javasound://")); -- } -- catch (Exception ee) { -- return "Couldn't create DataSource"; -- } -- } -- -- // Try to create a processor to handle the input jmf locator -- try { -- processor = javax.media.Manager.createProcessor(ds); -- } -- catch (NoProcessorException npe) { -- npe.printStackTrace(); -- return "Couldn't create processor"; -- } -- catch (IOException ioe) { -- ioe.printStackTrace(); -- return "IOException creating processor"; -- } -- -- // Wait for it to configure -- boolean result = waitForState(processor, Processor.Configured); -- if (!result){ -- return "Couldn't configure processor"; -- } -- -- // Get the tracks from the processor -- TrackControl[] tracks = processor.getTrackControls(); -- -- // Do we have atleast one track? -- if (tracks == null || tracks.length < 1){ -- return "Couldn't find tracks in processor"; -- } -- -- // Set the output content descriptor to RAW_RTP -- // This will limit the supported formats reported from -- // Track.getSupportedFormats to only valid RTP formats. -- ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP); -- processor.setContentDescriptor(cd); -- -- Format supported[]; -- Format chosen = null; -- boolean atLeastOneTrack = false; -- -- // Program the tracks. -- for (int i = 0; i < tracks.length; i++) { -- if (tracks[i].isEnabled()) { -- -- supported = tracks[i].getSupportedFormats(); -- -- if (supported.length > 0) { -- for (Format format : supported) { -- if (format instanceof AudioFormat) { -- if (this.format.matches(format)) -- chosen = format; -- } -- } -- if (chosen != null) { -- tracks[i].setFormat(chosen); -- LOGGER.error("Track " + i + " is set to transmit as:"); -- LOGGER.error(" " + chosen); -- -- if (tracks[i].getFormat() instanceof AudioFormat) { -- int packetRate = 20; -- PacketSizeControl pktCtrl = (PacketSizeControl) processor.getControl(PacketSizeControl.class.getName()); -- if (pktCtrl != null) { -- try { -- pktCtrl.setPacketSize(getPacketSize(tracks[i].getFormat(), packetRate)); -- } -- catch (IllegalArgumentException e) { -- pktCtrl.setPacketSize(80); -- // Do nothing -- } -- } -- -- if (tracks[i].getFormat().getEncoding().equals(AudioFormat.ULAW_RTP)) { -- Codec codec[] = new Codec[3]; -- -- codec[0] = new com.ibm.media.codec.audio.rc.RCModule(); -- codec[1] = new com.ibm.media.codec.audio.ulaw.JavaEncoder(); -- codec[2] = new com.sun.media.codec.audio.ulaw.Packetizer(); -- ((com.sun.media.codec.audio.ulaw.Packetizer) codec -- [2]).setPacketSize(160); -- -- try { -- tracks[i].setCodecChain(codec); -- } -- catch (UnsupportedPlugInException e) { -- e.printStackTrace(); -- } -- } -- -- } -- -- atLeastOneTrack = true; -- } -- else -- tracks[i].setEnabled(false); -- } -- else -- tracks[i].setEnabled(false); -- } -- } -- -- if (!atLeastOneTrack) -- return "Couldn't set any of the tracks to a valid RTP format"; -- -- result = waitForState(processor, Controller.Realized); -- if (!result) -- return "Couldn't realize processor"; -- -- // Get the output data source of the processor -- dataOutput = processor.getDataOutput(); -- -- return null; -- } -- -- /** -- * Get the best packet size for a given codec and a codec rate -- * -- * @param codecFormat -- * @param milliseconds -- * @return -- * @throws IllegalArgumentException -- */ -- private int getPacketSize(Format codecFormat, int milliseconds) throws IllegalArgumentException { -- String encoding = codecFormat.getEncoding(); -- if (encoding.equalsIgnoreCase(AudioFormat.GSM) || -- encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) { -- return milliseconds * 4; // 1 byte per millisec -- } -- else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) || -- encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) { -- return milliseconds * 8; -- } -- else { -- throw new IllegalArgumentException("Unknown codec type"); -- } -- } -- -- /** -- * Use the RTPManager API to create sessions for each jmf -- * track of the processor. -- * -- * @return description -- */ -- private String createTransmitter() { -- -- // Cheated. Should have checked the type. -- PushBufferDataSource pbds = (PushBufferDataSource) dataOutput; -- PushBufferStream pbss[] = pbds.getStreams(); -- -- rtpMgrs = new RTPManager[pbss.length]; -- SessionAddress localAddr, destAddr; -- InetAddress ipAddr; -- SendStream sendStream; -- audioReceiver = new AudioReceiver(this, jingleMediaSession); -- int port; -- -- for (int i = 0; i < pbss.length; i++) { -- try { -- rtpMgrs[i] = RTPManager.newInstance(); -- -- port = portBase + 2 * i; -- ipAddr = InetAddress.getByName(remoteIpAddress); -- -- localAddr = new SessionAddress(InetAddress.getByName(this.localIpAddress), -- localPort); -- -- destAddr = new SessionAddress(ipAddr, port); -- -- rtpMgrs[i].addReceiveStreamListener(audioReceiver); -- rtpMgrs[i].addSessionListener(audioReceiver); -- -- BufferControl bc = (BufferControl) rtpMgrs[i].getControl("javax.media.control.BufferControl"); -- if (bc != null) { -- int bl = 160; -- bc.setBufferLength(bl); -- } -- -- try { -- -- rtpMgrs[i].initialize(localAddr); -- -- } -- catch (InvalidSessionAddressException e) { -- // In case the local address is not allowed to read, we user another local address -- SessionAddress sessAddr = new SessionAddress(); -- localAddr = new SessionAddress(sessAddr.getDataAddress(), -- localPort); -- rtpMgrs[i].initialize(localAddr); -- } -- -- rtpMgrs[i].addTarget(destAddr); -- -- LOGGER.error("Created RTP session at " + localPort + " to: " + remoteIpAddress + " " + port); -- -- sendStream = rtpMgrs[i].createSendStream(dataOutput, i); -- -- sendStreams.add(sendStream); -- -- sendStream.start(); -- -- } -- catch (Exception e) { -- e.printStackTrace(); -- return e.getMessage(); -- } -- } -- -- return null; -- } -- -- /** -- * Set transmit activity. If the active is true, the instance should trasmit. -- * If it is set to false, the instance should pause transmit. -- * -- * @param active active state -- */ -- public void setTrasmit(boolean active) { -- for (SendStream sendStream : sendStreams) { -- try { -- if (active) { -- sendStream.start(); -- LOGGER.debug("START"); -- } -- else { -- sendStream.stop(); -- LOGGER.debug("STOP"); -- } -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- -- } -- } -- -- /** -- * ************************************************************* -- * Convenience methods to handle processor's state changes. -- * ************************************************************** -- */ -- -- private Integer stateLock = 0; -- private boolean failed = false; -- -- Integer getStateLock() { -- return stateLock; -- } -- -- void setFailed() { -- failed = true; -- } -- -- private synchronized boolean waitForState(Processor p, int state) { -- p.addControllerListener(new StateListener()); -- failed = false; -- -- // Call the required method on the processor -- if (state == Processor.Configured) { -- p.configure(); -- } -- else if (state == Processor.Realized) { -- p.realize(); -- } -- -- // Wait until we get an event that confirms the -- // success of the method, or a failure event. -- // See StateListener inner class -- while (p.getState() < state && !failed) { -- synchronized (getStateLock()) { -- try { -- getStateLock().wait(); -- } -- catch (InterruptedException ie) { -- return false; -- } -- } -- } -- -- return !failed; -- } -- -- /** -- * ************************************************************* -- * Inner Classes -- * ************************************************************** -- */ -- -- class StateListener implements ControllerListener { -- -- public void controllerUpdate(ControllerEvent ce) { -- -- // If there was an error during configure or -- // realize, the processor will be closed -- if (ce instanceof ControllerClosedEvent) -- setFailed(); -- -- // All controller events, send a notification -- // to the waiting thread in waitForState method. -- if (ce != null) { -- synchronized (getStateLock()) { -- getStateLock().notifyAll(); -- } -- } -- } -- } -- -- public static void main(String args[]) { -- -- InetAddress localhost; -- try { -- localhost = InetAddress.getLocalHost(); -- -- AudioChannel audioChannel0 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7002, 7020, new AudioFormat(AudioFormat.GSM_RTP), null); -- AudioChannel audioChannel1 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7020, 7002, new AudioFormat(AudioFormat.GSM_RTP), null); -- -- audioChannel0.start(); -- audioChannel1.start(); -- -- try { -- Thread.sleep(5000); -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- -- audioChannel0.setTrasmit(false); -- audioChannel1.setTrasmit(false); -- -- try { -- Thread.sleep(5000); -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- -- audioChannel0.setTrasmit(true); -- audioChannel1.setTrasmit(true); -- -- try { -- Thread.sleep(5000); -- } -- catch (InterruptedException e) { -- e.printStackTrace(); -- } -- -- audioChannel0.stop(); -- audioChannel1.stop(); -- -- } -- catch (UnknownHostException e) { -- e.printStackTrace(); -- } -- -- } --} -\ No newline at end of file -Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (working copy) -@@ -1,55 +0,0 @@ --/** -- * $RCSfile: AudioFormatUtils.java,v $ -- * $Revision: 1.1 $ -- * $Date: 08/11/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jmf; -- --import org.jivesoftware.smackx.jingle.media.PayloadType; -- --import javax.media.format.AudioFormat; -- --/** -- * Audio Format Utils. -- * -- * @author Thiago Camargo -- */ --public class AudioFormatUtils { -- -- /** -- * Return a JMF AudioFormat for a given Jingle Payload type. -- * Return null if the payload is not supported by this jmf API. -- * -- * @param payloadtype payloadtype -- * @return correspondent audioType -- */ -- public static AudioFormat getAudioFormat(PayloadType payloadtype) { -- -- switch (payloadtype.getId()) { -- case 0: -- return new AudioFormat(AudioFormat.ULAW_RTP); -- case 3: -- return new AudioFormat(AudioFormat.GSM_RTP); -- case 4: -- return new AudioFormat(AudioFormat.G723_RTP); -- default: -- return null; -- } -- -- } -- --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (working copy) -@@ -1,134 +0,0 @@ --/** -- * $RCSfile: SpeexMediaManager.java,v $ -- * $Revision: 1.3 $ -- * $Date: 25/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jspeex; -- --import java.io.File; --import java.io.IOException; --import java.util.ArrayList; --import java.util.List; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaManager; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; --import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * Implements a jingleMediaManager using JMF based API and JSpeex. -- * It supports Speex codec. -- * This API only currently works on windows. -- * -- * @author Thiago Camargo -- */ --public class SpeexMediaManager extends JingleMediaManager { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class); -- -- public static final String MEDIA_NAME = "Speex"; -- -- private List payloads = new ArrayList(); -- -- public SpeexMediaManager(JingleTransportManager transportManager) { -- super(transportManager); -- setupPayloads(); -- setupJMF(); -- } -- -- /** -- * Returns a new jingleMediaSession -- * -- * @param payloadType payloadType -- * @param remote remote Candidate -- * @param local local Candidate -- * @return JingleMediaSession -- */ -- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { -- return new AudioMediaSession(payloadType, remote, local, null,null); -- } -- -- /** -- * Setup API supported Payloads -- */ -- private void setupPayloads() { -- payloads.add(new PayloadType.Audio(15, "speex")); -- } -- -- /** -- * Return all supported Payloads for this Manager -- * -- * @return The Payload List -- */ -- public List getPayloads() { -- return payloads; -- } -- -- /** -- * Runs JMFInit the first time the application is started so that capture -- * devices are properly detected and initialized by JMF. -- */ -- public static void setupJMF() { -- // .jmf is the place where we store the jmf.properties file used -- // by JMF. if the directory does not exist or it does not contain -- // a jmf.properties file. or if the jmf.properties file has 0 length -- // then this is the first time we're running and should continue to -- // with JMFInit -- String homeDir = System.getProperty("user.home"); -- File jmfDir = new File(homeDir, ".jmf"); -- String classpath = System.getProperty("java.class.path"); -- classpath += System.getProperty("path.separator") -- + jmfDir.getAbsolutePath(); -- System.setProperty("java.class.path", classpath); -- -- if (!jmfDir.exists()) -- jmfDir.mkdir(); -- -- File jmfProperties = new File(jmfDir, "jmf.properties"); -- -- if (!jmfProperties.exists()) { -- try { -- jmfProperties.createNewFile(); -- } -- catch (IOException ex) { -- LOGGER.debug("Failed to create jmf.properties"); -- ex.printStackTrace(); -- } -- } -- -- // if we're running on linux checkout that libjmutil.so is where it -- // should be and put it there. -- runLinuxPreInstall(); -- -- if (jmfProperties.length() == 0) { -- new JMFInit(null, false); -- } -- -- } -- -- private static void runLinuxPreInstall() { -- // @TODO Implement Linux Pre-Install -- } -- -- public String getName() { -- return MEDIA_NAME; -- } --} -Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java -=================================================================== ---- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (revision 11644) -+++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (working copy) -@@ -1,245 +0,0 @@ --/** -- * $RCSfile: AudioMediaSession.java,v $ -- * $Revision: 1.1 $ -- * $Date: 25/12/2006 -- *

-- * Copyright 2003-2006 Jive Software. -- *

-- * All rights reserved. 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 org.jivesoftware.smackx.jingle.mediaimpl.jspeex; -- --import java.io.IOException; --import java.net.DatagramSocket; --import java.net.InetAddress; --import java.net.ServerSocket; --import java.security.GeneralSecurityException; -- --import javax.media.NoProcessorException; --import javax.media.format.UnsupportedFormatException; --import javax.media.rtp.rtcp.SenderReport; --import javax.media.rtp.rtcp.SourceDescription; -- --import mil.jfcom.cie.media.session.MediaSession; --import mil.jfcom.cie.media.session.MediaSessionListener; --import mil.jfcom.cie.media.session.StreamPlayer; --import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat; -- --import org.jivesoftware.smackx.jingle.JingleSession; --import org.jivesoftware.smackx.jingle.SmackLogger; --import org.jivesoftware.smackx.jingle.media.JingleMediaSession; --import org.jivesoftware.smackx.jingle.media.PayloadType; --import org.jivesoftware.smackx.jingle.nat.TransportCandidate; -- --/** -- * This Class implements a complete JingleMediaSession. -- * It sould be used to transmit and receive audio captured from the Mic. -- * This Class should be automaticly controlled by JingleSession. -- * But you could also use in any VOIP application. -- * For better NAT Traversal support this implementation don't support only receive or only transmit. -- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() -- * -- * @author Thiago Camargo -- */ -- --public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener { -- -- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class); -- -- private MediaSession mediaSession; -- -- /** -- * Create a Session using Speex Codec -- * -- * @param localhost localHost -- * @param localPort localPort -- * @param remoteHost remoteHost -- * @param remotePort remotePort -- * @param eventHandler eventHandler -- * @param quality quality -- * @param secure secure -- * @param micOn micOn -- * @return MediaSession -- * @throws NoProcessorException -- * @throws UnsupportedFormatException -- * @throws IOException -- * @throws GeneralSecurityException -- */ -- public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException { -- -- SpeexFormat.setFramesPerPacket(1); -- /** -- * The master key. Hardcoded for now. -- */ -- byte[] masterKey = new byte[]{(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39}; -- -- /** -- * The master salt. Hardcoded for now. -- */ -- byte[] masterSalt = new byte[]{0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6}; -- -- DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort); -- MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt); -- session.setListener(eventHandler); -- -- session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester@je.jfcom.mil", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_LOC, InetAddress.getByName(localhost) + " Port " + session.getLocalDataPort(), 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JFCOM CDCIE Audio Chat", 1, false)}); -- return session; -- } -- -- -- /** -- * Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates -- * -- * @param payloadType Payload of the jmf -- * @param remote the remote information. The candidate that the jmf will be sent to. -- * @param local the local information. The candidate that will receive the jmf -- * @param locator media locator -- */ -- public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, -- final TransportCandidate local, String locator, JingleSession jingleSession) { -- super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession); -- initialize(); -- } -- -- /** -- * Initialize the Audio Channel to make it able to send and receive audio -- */ -- public void initialize() { -- -- String ip; -- String localIp; -- int localPort; -- int remotePort; -- -- if (this.getLocal().getSymmetric() != null) { -- ip = this.getLocal().getIp(); -- localIp = this.getLocal().getLocalIp(); -- localPort = getFreePort(); -- remotePort = this.getLocal().getSymmetric().getPort(); -- -- LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); -- -- } -- else { -- ip = this.getRemote().getIp(); -- localIp = this.getLocal().getLocalIp(); -- localPort = this.getLocal().getPort(); -- remotePort = this.getRemote().getPort(); -- } -- -- try { -- mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true); -- } -- catch (NoProcessorException e) { -- e.printStackTrace(); -- } -- catch (UnsupportedFormatException e) { -- e.printStackTrace(); -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- catch (GeneralSecurityException e) { -- e.printStackTrace(); -- } -- } -- -- /** -- * Starts transmission and for NAT Traversal reasons start receiving also. -- */ -- public void startTrasmit() { -- try { -- LOGGER.debug("start"); -- mediaSession.start(true); -- this.mediaReceived(""); -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- } -- -- /** -- * Set transmit activity. If the active is true, the instance should trasmit. -- * If it is set to false, the instance should pause transmit. -- * -- * @param active active state -- */ -- public void setTrasmit(boolean active) { -- // Do nothing -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void startReceive() { -- // Do nothing -- } -- -- /** -- * Stops transmission and for NAT Traversal reasons stop receiving also. -- */ -- public void stopTrasmit() { -- if (mediaSession != null) -- mediaSession.close(); -- } -- -- /** -- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf -- */ -- public void stopReceive() { -- // Do nothing -- } -- -- public void newStreamIdentified(StreamPlayer streamPlayer) { -- } -- -- public void senderReportReceived(SenderReport report) { -- } -- -- public void streamClosed(StreamPlayer stream, boolean timeout) { -- } -- -- /** -- * Obtain a free port we can use. -- * -- * @return A free port number. -- */ -- protected int getFreePort() { -- ServerSocket ss; -- int freePort = 0; -- -- for (int i = 0; i < 10; i++) { -- freePort = (int) (10000 + Math.round(Math.random() * 10000)); -- freePort = freePort % 2 == 0 ? freePort : freePort + 1; -- try { -- ss = new ServerSocket(freePort); -- freePort = ss.getLocalPort(); -- ss.close(); -- return freePort; -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- } -- try { -- ss = new ServerSocket(0); -- freePort = ss.getLocalPort(); -- ss.close(); -- } -- catch (IOException e) { -- e.printStackTrace(); -- } -- return freePort; -- } --}