aboutsummaryrefslogtreecommitdiff
path: root/asmack-master/jingle/60-remove-jingle_mediaimpl.patch
diff options
context:
space:
mode:
Diffstat (limited to 'asmack-master/jingle/60-remove-jingle_mediaimpl.patch')
-rw-r--r--asmack-master/jingle/60-remove-jingle_mediaimpl.patch4039
1 files changed, 4039 insertions, 0 deletions
diff --git a/asmack-master/jingle/60-remove-jingle_mediaimpl.patch b/asmack-master/jingle/60-remove-jingle_mediaimpl.patch
new file mode 100644
index 0000000..9aefc18
--- /dev/null
+++ b/asmack-master/jingle/60-remove-jingle_mediaimpl.patch
@@ -0,0 +1,4039 @@
+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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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<PayloadType> payloads = new ArrayList<PayloadType>();
+-
+- private PayloadType preferredPayloadType = null;
+-
+- public TestMediaManager(JingleTransportManager transportManager) {
+- super(transportManager);
+- }
+-
+- /**
+- * Return all supported Payloads for this Manager.
+- *
+- * @return The Payload List
+- */
+- public List<PayloadType> getPayloads() {
+- return payloads;
+- }
+-
+- public void setPayloads(List<PayloadType> 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>();
+- //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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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<PayloadType> payloads = new ArrayList<PayloadType>();
+-
+- 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<PayloadType> 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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<JingleMediaManager> managers = new ArrayList<JingleMediaManager>();
+-
+- 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<PayloadType> getPayloads() {
+- List<PayloadType> list = new ArrayList<PayloadType>();
+- 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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.
+- * <i>This API only currently works on windows and Mac.</i>
+- *
+- * @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<PayloadType> payloads = new ArrayList<PayloadType>();
+- 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<PayloadType> 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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.
+- * <p/>
+- * Send from portA to portB and receive from portB in portA.
+- * <p/>
+- * Sending
+- * portA ---> portB
+- * <p/>
+- * Receiving
+- * portB ---> portA
+- * <p/>
+- * <i>Transmit and Receive are interdependents. To receive you MUST trasmit. </i>
+- *
+- * @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<SendStream> sendStreams = new ArrayList<SendStream>();
+-
+- 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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.
+- * <i>This API only currently works on windows.</i>
+- *
+- * @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<PayloadType> payloads = new ArrayList<PayloadType>();
+-
+- 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<PayloadType> 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
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * 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;
+- }
+-}