1 Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java 2 =================================================================== 3 --- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (revision 11644) 4 +++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (working copy) 5 @@ -1,92 +0,0 @@ 6 -/** 7 - * $RCSfile: TestMediaSession.java,v $ 8 - * $Revision: 1.1 $ 9 - * $Date: 08/11/2006 10 - * <p/> 11 - * Copyright 2003-2006 Jive Software. 12 - * <p/> 13 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 14 - * you may not use this file except in compliance with the License. 15 - * You may obtain a copy of the License at 16 - * <p/> 17 - * http://www.apache.org/licenses/LICENSE-2.0 18 - * <p/> 19 - * Unless required by applicable law or agreed to in writing, software 20 - * distributed under the License is distributed on an "AS IS" BASIS, 21 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 - * See the License for the specific language governing permissions and 23 - * limitations under the License. 24 - */ 25 -package org.jivesoftware.smackx.jingle.mediaimpl.test; 26 - 27 -import org.jivesoftware.smackx.jingle.JingleSession; 28 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 29 -import org.jivesoftware.smackx.jingle.media.PayloadType; 30 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 31 - 32 -/** 33 - * This Class implements a complete JingleMediaSession for unit testing. 34 - * 35 - * @author Thiago Camargo 36 - */ 37 -public class TestMediaSession extends JingleMediaSession { 38 - 39 - /** 40 - * Creates a TestMediaSession with defined payload type, remote and local candidates 41 - * 42 - * @param payloadType Payload of the jmf 43 - * @param remote the remote information. The candidate that the jmf will be sent to. 44 - * @param local the local information. The candidate that will receive the jmf 45 - * @param locator media locator 46 - */ 47 - public TestMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, 48 - final String locator, JingleSession jingleSession) { 49 - super(payloadType, remote, local, "Test", jingleSession); 50 - initialize(); 51 - } 52 - 53 - /** 54 - * Initialize the screen share channels. 55 - */ 56 - public void initialize() { 57 - 58 - } 59 - 60 - /** 61 - * Starts transmission and for NAT Traversal reasons start receiving also. 62 - */ 63 - public void startTrasmit() { 64 - 65 - } 66 - 67 - /** 68 - * Set transmit activity. If the active is true, the instance should trasmit. 69 - * If it is set to false, the instance should pause transmit. 70 - * 71 - * @param active active state 72 - */ 73 - public void setTrasmit(boolean active) { 74 - 75 - } 76 - 77 - /** 78 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 79 - */ 80 - public void startReceive() { 81 - // Do nothing 82 - } 83 - 84 - /** 85 - * Stops transmission and for NAT Traversal reasons stop receiving also. 86 - */ 87 - public void stopTrasmit() { 88 - 89 - } 90 - 91 - /** 92 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 93 - */ 94 - public void stopReceive() { 95 - 96 - } 97 -} 98 Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java 99 =================================================================== 100 --- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (revision 11644) 101 +++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (working copy) 102 @@ -1,93 +0,0 @@ 103 -/** 104 - * $RCSfile: TestMediaManager.java,v $ 105 - * $Revision: 1.3 $ 106 - * $Date: 25/12/2006 107 - * <p/> 108 - * Copyright 2003-2006 Jive Software. 109 - * <p/> 110 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 111 - * you may not use this file except in compliance with the License. 112 - * You may obtain a copy of the License at 113 - * <p/> 114 - * http://www.apache.org/licenses/LICENSE-2.0 115 - * <p/> 116 - * Unless required by applicable law or agreed to in writing, software 117 - * distributed under the License is distributed on an "AS IS" BASIS, 118 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 119 - * See the License for the specific language governing permissions and 120 - * limitations under the License. 121 - */ 122 - 123 -package org.jivesoftware.smackx.jingle.mediaimpl.test; 124 - 125 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 126 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 127 -import org.jivesoftware.smackx.jingle.media.PayloadType; 128 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 129 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 130 -import org.jivesoftware.smackx.jingle.JingleSession; 131 - 132 -import java.util.*; 133 - 134 -/** 135 - * Implements a MediaManager for test purposes. 136 - * 137 - * @author Thiago Camargo 138 - */ 139 - 140 -public class TestMediaManager extends JingleMediaManager { 141 - 142 - public static final String MEDIA_NAME = "TestMedia"; 143 - 144 - private List<PayloadType> payloads = new ArrayList<PayloadType>(); 145 - 146 - private PayloadType preferredPayloadType = null; 147 - 148 - public TestMediaManager(JingleTransportManager transportManager) { 149 - super(transportManager); 150 - } 151 - 152 - /** 153 - * Return all supported Payloads for this Manager. 154 - * 155 - * @return The Payload List 156 - */ 157 - public List<PayloadType> getPayloads() { 158 - return payloads; 159 - } 160 - 161 - public void setPayloads(List<PayloadType> payloads) { 162 - this.payloads.addAll(payloads); 163 - } 164 - 165 - /** 166 - * Returns a new JingleMediaSession 167 - * 168 - * @param payloadType payloadType 169 - * @param remote remote Candidate 170 - * @param local local Candidate 171 - * @return JingleMediaSession JingleMediaSession 172 - */ 173 - public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, 174 - final TransportCandidate local, final JingleSession jingleSession) { 175 - TestMediaSession session = null; 176 - 177 - session = new TestMediaSession(payloadType, remote, local, "", jingleSession); 178 - 179 - return session; 180 - } 181 - 182 - public PayloadType getPreferredPayloadType() { 183 - if (preferredPayloadType != null) 184 - return preferredPayloadType; 185 - return super.getPreferredPayloadType(); 186 - } 187 - 188 - public void setPreferredPayloadType(PayloadType preferredPayloadType) { 189 - this.preferredPayloadType = preferredPayloadType; 190 - } 191 - 192 - public String getName() { 193 - return MEDIA_NAME; 194 - } 195 -} 196 Index: org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java 197 =================================================================== 198 --- org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (revision 11644) 199 +++ org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (working copy) 200 @@ -1,282 +0,0 @@ 201 -package org.jivesoftware.smackx.jingle.mediaimpl; 202 - 203 -import java.awt.Frame; 204 -import java.awt.TextArea; 205 -import java.awt.Toolkit; 206 -import java.util.Vector; 207 - 208 -import javax.media.Format; 209 -import javax.media.PlugInManager; 210 -import javax.media.Renderer; 211 -import javax.media.format.AudioFormat; 212 - 213 -import org.jivesoftware.smackx.jingle.SmackLogger; 214 - 215 -import com.sun.media.ExclusiveUse; 216 -import com.sun.media.util.Registry; 217 - 218 -public class JMFInit extends Frame implements Runnable { 219 - 220 - private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class); 221 - 222 - private String tempDir = "/tmp"; 223 - 224 - private boolean done = false; 225 - 226 - private String userHome; 227 - 228 - private boolean visible = false; 229 - 230 - public JMFInit(String[] args, boolean visible) { 231 - super("Initializing JMF..."); 232 - 233 - this.visible = visible; 234 - 235 - Registry.set("secure.allowCaptureFromApplets", true); 236 - Registry.set("secure.allowSaveFileFromApplets", true); 237 - 238 - updateTemp(args); 239 - 240 - try { 241 - Registry.commit(); 242 - } 243 - catch (Exception e) { 244 - 245 - message("Failed to commit to JMFRegistry!"); 246 - } 247 - 248 - Thread detectThread = new Thread(this); 249 - detectThread.run(); 250 - 251 - /* 252 - * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try { 253 - * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { } 254 - * slept += 500; } 255 - * 256 - * if (!done) { console.error("Detection is taking too long! 257 - * Aborting!"); message("Detection is taking too long! Aborting!"); } 258 - * 259 - * try { Thread.currentThread().sleep(2000); } catch 260 - * (InterruptedException ie) { } 261 - */ 262 - } 263 - 264 - public void run() { 265 - detectDirectAudio(); 266 - detectS8DirectAudio(); 267 - detectCaptureDevices(); 268 - done = true; 269 - } 270 - 271 - private void updateTemp(String[] args) { 272 - if (args != null && args.length > 0) { 273 - tempDir = args[0]; 274 - 275 - message("Setting cache directory to " + tempDir); 276 - Registry r = new Registry(); 277 - try { 278 - r.set("secure.cacheDir", tempDir); 279 - r.commit(); 280 - 281 - message("Updated registry"); 282 - } 283 - catch (Exception e) { 284 - message("Couldn't update registry!"); 285 - } 286 - } 287 - } 288 - 289 - private void detectCaptureDevices() { 290 - // check if JavaSound capture is available 291 - message("Looking for Audio capturer"); 292 - Class dsauto; 293 - try { 294 - dsauto = Class.forName("DirectSoundAuto"); 295 - dsauto.newInstance(); 296 - message("Finished detecting DirectSound capturer"); 297 - } 298 - catch (ThreadDeath td) { 299 - throw td; 300 - } 301 - catch (Throwable t) { 302 - //Do nothing 303 - } 304 - 305 - Class jsauto; 306 - try { 307 - jsauto = Class.forName("JavaSoundAuto"); 308 - jsauto.newInstance(); 309 - message("Finished detecting javasound capturer"); 310 - } 311 - catch (ThreadDeath td) { 312 - throw td; 313 - } 314 - catch (Throwable t) { 315 - message("JavaSound capturer detection failed!"); 316 - } 317 - 318 - /* 319 - // Check if VFWAuto or SunVideoAuto is available 320 - message("Looking for video capture devices"); 321 - Class auto = null; 322 - Class autoPlus = null; 323 - try { 324 - auto = Class.forName("VFWAuto"); 325 - } 326 - catch (Exception e) { 327 - } 328 - if (auto == null) { 329 - try { 330 - auto = Class.forName("SunVideoAuto"); 331 - } 332 - catch (Exception ee) { 333 - 334 - } 335 - try { 336 - autoPlus = Class.forName("SunVideoPlusAuto"); 337 - } 338 - catch (Exception ee) { 339 - 340 - } 341 - } 342 - if (auto == null) { 343 - try { 344 - auto = Class.forName("V4LAuto"); 345 - } 346 - catch (Exception ee) { 347 - 348 - } 349 - } 350 - try { 351 - Object instance = auto.newInstance(); 352 - if (autoPlus != null) { 353 - Object instancePlus = autoPlus.newInstance(); 354 - } 355 - 356 - message("Finished detecting video capture devices"); 357 - } 358 - catch (ThreadDeath td) { 359 - throw td; 360 - } 361 - catch (Throwable t) { 362 - 363 - message("Capture device detection failed!"); 364 - } 365 - */ 366 - } 367 - 368 - private void detectDirectAudio() { 369 - Class cls; 370 - int plType = PlugInManager.RENDERER; 371 - String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; 372 - try { 373 - // Check if this is the Windows Performance Pack - hack 374 - cls = Class.forName("VFWAuto"); 375 - // Check if DS capture is supported, otherwise fail DS renderer 376 - // since NT doesn't have capture 377 - cls = Class.forName("com.sun.media.protocol.dsound.DSound"); 378 - // Find the renderer class and instantiate it. 379 - cls = Class.forName(dar); 380 - 381 - Renderer rend = (Renderer) cls.newInstance(); 382 - try { 383 - // Set the format and open the device 384 - AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16, 385 - 2); 386 - rend.setInputFormat(af); 387 - rend.open(); 388 - Format[] inputFormats = rend.getSupportedInputFormats(); 389 - // Register the device 390 - PlugInManager.addPlugIn(dar, inputFormats, new Format[0], 391 - plType); 392 - // Move it to the top of the list 393 - Vector rendList = PlugInManager.getPlugInList(null, null, 394 - plType); 395 - int listSize = rendList.size(); 396 - if (rendList.elementAt(listSize - 1).equals(dar)) { 397 - rendList.removeElementAt(listSize - 1); 398 - rendList.insertElementAt(dar, 0); 399 - PlugInManager.setPlugInList(rendList, plType); 400 - PlugInManager.commit(); 401 - // Log.debug("registered"); 402 - } 403 - rend.close(); 404 - } 405 - catch (Throwable t) { 406 - // Log.debug("Error " + t); 407 - } 408 - } 409 - catch (Throwable tt) { 410 - //Do nothing 411 - } 412 - } 413 - 414 - private void detectS8DirectAudio() { 415 - Class cls; 416 - int plType = PlugInManager.RENDERER; 417 - String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; 418 - try { 419 - // Check if this is the solaris Performance Pack - hack 420 - cls = Class.forName("SunVideoAuto"); 421 - 422 - // Find the renderer class and instantiate it. 423 - cls = Class.forName(dar); 424 - 425 - Renderer rend = (Renderer) cls.newInstance(); 426 - 427 - if (rend instanceof ExclusiveUse 428 - && !((ExclusiveUse) rend).isExclusive()) { 429 - // sol8+, DAR supports mixing 430 - Vector rendList = PlugInManager.getPlugInList(null, null, 431 - plType); 432 - int listSize = rendList.size(); 433 - boolean found = false; 434 - String rname = null; 435 - 436 - for (int i = 0; i < listSize; i++) { 437 - rname = (String) (rendList.elementAt(i)); 438 - if (rname.equals(dar)) { // DAR is in the registry 439 - found = true; 440 - rendList.removeElementAt(i); 441 - break; 442 - } 443 - } 444 - 445 - if (found) { 446 - rendList.insertElementAt(dar, 0); 447 - PlugInManager.setPlugInList(rendList, plType); 448 - PlugInManager.commit(); 449 - } 450 - } 451 - } 452 - catch (Throwable tt) { 453 - //Do nothing 454 - } 455 - } 456 - 457 - private void message(String mesg) { 458 - LOGGER.debug(mesg); 459 - } 460 - 461 - private void createGUI() { 462 - TextArea textBox = new TextArea(5, 50); 463 - add("Center", textBox); 464 - textBox.setEditable(false); 465 - addNotify(); 466 - pack(); 467 - 468 - int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize() 469 - .getWidth(); 470 - int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize() 471 - .getHeight(); 472 - 473 - setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2); 474 - 475 - setVisible(visible); 476 - 477 - } 478 - 479 - public static void start(boolean visible) { 480 - new JMFInit(null, visible); 481 - } 482 -} 483 Index: org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java 484 =================================================================== 485 --- org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (revision 11644) 486 +++ org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (working copy) 487 @@ -1,174 +0,0 @@ 488 -/** 489 - * $RCSfile: Demo.java,v $ 490 - * $Revision: 1.3 $ 491 - * $Date: 28/12/2006 492 - * <p/> 493 - * Copyright 2003-2006 Jive Software. 494 - * <p/> 495 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 496 - * you may not use this file except in compliance with the License. 497 - * You may obtain a copy of the License at 498 - * <p/> 499 - * http://www.apache.org/licenses/LICENSE-2.0 500 - * <p/> 501 - * Unless required by applicable law or agreed to in writing, software 502 - * distributed under the License is distributed on an "AS IS" BASIS, 503 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 504 - * See the License for the specific language governing permissions and 505 - * limitations under the License. 506 - */ 507 -package org.jivesoftware.smackx.jingle.mediaimpl.demo; 508 - 509 -import org.jivesoftware.smack.Connection; 510 -import org.jivesoftware.smack.XMPPConnection; 511 -import org.jivesoftware.smack.XMPPException; 512 -import org.jivesoftware.smackx.jingle.JingleManager; 513 -import org.jivesoftware.smackx.jingle.JingleSession; 514 -import org.jivesoftware.smackx.jingle.JingleSessionRequest; 515 -import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener; 516 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 517 -import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager; 518 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager; 519 -import org.jivesoftware.smackx.jingle.nat.ICETransportManager; 520 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 521 - 522 -import javax.swing.*; 523 -import java.awt.event.ActionEvent; 524 -import java.util.ArrayList; 525 -import java.util.List; 526 - 527 -/** 528 - * Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls. 529 - * Parameters: Server User Pass. 530 - */ 531 -public class Demo extends JFrame { 532 - 533 - private JingleTransportManager transportManager = null; 534 - private Connection xmppConnection = null; 535 - 536 - private String server = null; 537 - private String user = null; 538 - private String pass = null; 539 - 540 - private JingleManager jm = null; 541 - private JingleSession incoming = null; 542 - private JingleSession outgoing = null; 543 - 544 - private JTextField jid; 545 - 546 - public Demo(String server, String user, String pass) { 547 - 548 - this.server = server; 549 - this.user = user; 550 - this.pass = pass; 551 - 552 - if (user.equals("jeffw")) { 553 - jid = new JTextField("eowyn" + "@" + server + "/Smack"); 554 - } else { 555 - jid = new JTextField("jeffw" + "@" + server + "/Smack"); 556 - } 557 - 558 - xmppConnection = new XMPPConnection(server); 559 - try { 560 - xmppConnection.connect(); 561 - xmppConnection.login(user, pass); 562 - initialize(); 563 - } 564 - catch (XMPPException e) { 565 - e.printStackTrace(); 566 - } 567 - } 568 - 569 - public void initialize() { 570 - ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478); 571 - List<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>(); 572 - //mediaManagers.add(new JmfMediaManager(icetm0)); 573 - mediaManagers.add(new SpeexMediaManager(icetm0)); 574 - mediaManagers.add(new ScreenShareMediaManager(icetm0)); 575 - jm = new JingleManager(xmppConnection, mediaManagers); 576 - jm.addCreationListener(icetm0); 577 - 578 - jm.addJingleSessionRequestListener(new JingleSessionRequestListener() { 579 - public void sessionRequested(JingleSessionRequest request) { 580 - 581 -// if (incoming != null) 582 -// return; 583 - 584 - try { 585 - // Accept the call 586 - incoming = request.accept(); 587 - 588 - // Start the call 589 - incoming.startIncoming(); 590 - } 591 - catch (XMPPException e) { 592 - e.printStackTrace(); 593 - } 594 - 595 - } 596 - }); 597 - createGUI(); 598 - } 599 - 600 - public void createGUI() { 601 - 602 - JPanel jPanel = new JPanel(); 603 - 604 - jPanel.add(jid); 605 - 606 - jPanel.add(new JButton(new AbstractAction("Call") { 607 - public void actionPerformed(ActionEvent e) { 608 - if (outgoing != null) return; 609 - try { 610 - outgoing = jm.createOutgoingJingleSession(jid.getText()); 611 - outgoing.startOutgoing(); 612 - } 613 - catch (XMPPException e1) { 614 - e1.printStackTrace(); 615 - } 616 - } 617 - })); 618 - 619 - jPanel.add(new JButton(new AbstractAction("Hangup") { 620 - public void actionPerformed(ActionEvent e) { 621 - if (outgoing != null) 622 - try { 623 - outgoing.terminate(); 624 - } 625 - catch (XMPPException e1) { 626 - e1.printStackTrace(); 627 - } 628 - finally { 629 - outgoing = null; 630 - } 631 - if (incoming != null) 632 - try { 633 - incoming.terminate(); 634 - } 635 - catch (XMPPException e1) { 636 - e1.printStackTrace(); 637 - } 638 - finally { 639 - incoming = null; 640 - } 641 - } 642 - })); 643 - 644 - this.add(jPanel); 645 - 646 - } 647 - 648 - public static void main(String args[]) { 649 - 650 - Demo demo = null; 651 - 652 - if (args.length > 2) { 653 - demo = new Demo(args[0], args[1], args[2]); 654 - demo.pack(); 655 - demo.setVisible(true); 656 - demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 657 - } 658 - 659 - } 660 - 661 -} 662 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java 663 =================================================================== 664 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (revision 11644) 665 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (working copy) 666 @@ -1,206 +0,0 @@ 667 -/** 668 - * $RCSfile: ScreenShareSession.java,v $ 669 - * $Revision: 1.2 $ 670 - * $Date: 08/11/2006 671 - * <p/> 672 - * Copyright 2003-2006 Jive Software. 673 - * <p/> 674 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 675 - * you may not use this file except in compliance with the License. 676 - * You may obtain a copy of the License at 677 - * <p/> 678 - * http://www.apache.org/licenses/LICENSE-2.0 679 - * <p/> 680 - * Unless required by applicable law or agreed to in writing, software 681 - * distributed under the License is distributed on an "AS IS" BASIS, 682 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 683 - * See the License for the specific language governing permissions and 684 - * limitations under the License. 685 - */ 686 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare; 687 - 688 -import java.awt.Rectangle; 689 -import java.awt.event.WindowAdapter; 690 -import java.awt.event.WindowEvent; 691 -import java.io.IOException; 692 -import java.net.DatagramSocket; 693 -import java.net.InetAddress; 694 -import java.net.ServerSocket; 695 -import java.net.UnknownHostException; 696 - 697 -import javax.swing.JFrame; 698 -import javax.swing.JPanel; 699 - 700 -import org.jivesoftware.smackx.jingle.JingleSession; 701 -import org.jivesoftware.smackx.jingle.SmackLogger; 702 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 703 -import org.jivesoftware.smackx.jingle.media.PayloadType; 704 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder; 705 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder; 706 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageReceiver; 707 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter; 708 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 709 - 710 -/** 711 - * This Class implements a complete JingleMediaSession. 712 - * It sould be used to transmit and receive captured images from the Display. 713 - * This Class should be automaticly controlled by JingleSession. 714 - * For better NAT Traversal support this implementation don't support only receive or only transmit. 715 - * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() 716 - * 717 - * @author Thiago Camargo 718 - */ 719 -public class ScreenShareSession extends JingleMediaSession { 720 - 721 - private static final SmackLogger LOGGER = SmackLogger.getLogger(ScreenShareSession.class); 722 - 723 - private ImageTransmitter transmitter = null; 724 - private ImageReceiver receiver = null; 725 - private int width = 600; 726 - private int height = 600; 727 - 728 - /** 729 - * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates 730 - * 731 - * @param payloadType Payload of the jmf 732 - * @param remote the remote information. The candidate that the jmf will be sent to. 733 - * @param local the local information. The candidate that will receive the jmf 734 - * @param locator media locator 735 - */ 736 - public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, 737 - final String locator, JingleSession jingleSession) { 738 - super(payloadType, remote, local, "Screen", jingleSession); 739 - initialize(); 740 - } 741 - 742 - /** 743 - * Initialize the screen share channels. 744 - */ 745 - public void initialize() { 746 - 747 - JingleSession session = getJingleSession(); 748 - if ((session != null) && (session.getInitiator().equals(session.getConnection().getUser()))) { 749 - // If the initiator of the jingle session is us then we transmit a screen share. 750 - try { 751 - InetAddress remote = InetAddress.getByName(getRemote().getIp()); 752 - transmitter = new ImageTransmitter(new DatagramSocket(getLocal().getPort()), remote, getRemote().getPort(), 753 - new Rectangle(0, 0, width, height)); 754 - } catch (Exception e) { 755 - e.printStackTrace(); 756 - } 757 - 758 - } else { 759 - // Otherwise we receive a screen share. 760 - JFrame window = new JFrame(); 761 - JPanel jp = new JPanel(); 762 - window.add(jp); 763 - 764 - window.setLocation(0, 0); 765 - window.setSize(600, 600); 766 - 767 - window.addWindowListener(new WindowAdapter() { 768 - public void windowClosed(WindowEvent e) { 769 - receiver.stop(); 770 - } 771 - }); 772 - 773 - try { 774 - receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width, 775 - height); 776 - LOGGER.debug("Receiving on:" + receiver.getLocalPort()); 777 - } catch (UnknownHostException e) { 778 - e.printStackTrace(); 779 - } 780 - 781 - jp.add(receiver); 782 - receiver.setVisible(true); 783 - window.setAlwaysOnTop(true); 784 - window.setVisible(true); 785 - } 786 - } 787 - 788 - /** 789 - * Starts transmission and for NAT Traversal reasons start receiving also. 790 - */ 791 - public void startTrasmit() { 792 - new Thread(transmitter).start(); 793 - } 794 - 795 - /** 796 - * Set transmit activity. If the active is true, the instance should trasmit. 797 - * If it is set to false, the instance should pause transmit. 798 - * 799 - * @param active active state 800 - */ 801 - public void setTrasmit(boolean active) { 802 - transmitter.setTransmit(true); 803 - } 804 - 805 - /** 806 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 807 - */ 808 - public void startReceive() { 809 - // Do nothing 810 - } 811 - 812 - /** 813 - * Stops transmission and for NAT Traversal reasons stop receiving also. 814 - */ 815 - public void stopTrasmit() { 816 - if (transmitter != null) { 817 - transmitter.stop(); 818 - } 819 - } 820 - 821 - /** 822 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 823 - */ 824 - public void stopReceive() { 825 - if (receiver != null) { 826 - receiver.stop(); 827 - } 828 - } 829 - 830 - /** 831 - * Obtain a free port we can use. 832 - * 833 - * @return A free port number. 834 - */ 835 - protected int getFreePort() { 836 - ServerSocket ss; 837 - int freePort = 0; 838 - 839 - for (int i = 0; i < 10; i++) { 840 - freePort = (int) (10000 + Math.round(Math.random() * 10000)); 841 - freePort = freePort % 2 == 0 ? freePort : freePort + 1; 842 - try { 843 - ss = new ServerSocket(freePort); 844 - freePort = ss.getLocalPort(); 845 - ss.close(); 846 - return freePort; 847 - } catch (IOException e) { 848 - e.printStackTrace(); 849 - } 850 - } 851 - try { 852 - ss = new ServerSocket(0); 853 - freePort = ss.getLocalPort(); 854 - ss.close(); 855 - } catch (IOException e) { 856 - e.printStackTrace(); 857 - } 858 - return freePort; 859 - } 860 - 861 - public void setEncoder(ImageEncoder encoder) { 862 - if (encoder != null) { 863 - this.transmitter.setEncoder(encoder); 864 - } 865 - } 866 - 867 - public void setDecoder(ImageDecoder decoder) { 868 - if (decoder != null) { 869 - this.receiver.setDecoder(decoder); 870 - } 871 - } 872 -} 873 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java 874 =================================================================== 875 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (revision 11644) 876 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (working copy) 877 @@ -1,204 +0,0 @@ 878 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 879 - 880 -import java.awt.AWTException; 881 -import java.awt.Rectangle; 882 -import java.awt.Robot; 883 -import java.awt.image.BufferedImage; 884 -import java.awt.image.PixelGrabber; 885 -import java.io.ByteArrayOutputStream; 886 -import java.io.IOException; 887 -import java.net.DatagramPacket; 888 -import java.net.DatagramSocket; 889 -import java.net.InetAddress; 890 -import java.util.Arrays; 891 - 892 -import org.jivesoftware.smackx.jingle.SmackLogger; 893 - 894 -/** 895 - * UDP Image Receiver. 896 - * It uses PNG Tiles into UDP packets. 897 - * 898 - * @author Thiago Rocha Camargo 899 - */ 900 -public class ImageTransmitter implements Runnable { 901 - 902 - private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class); 903 - 904 - private Robot robot; 905 - private InetAddress localHost; 906 - private InetAddress remoteHost; 907 - private int localPort; 908 - private int remotePort; 909 - public static final int tileWidth = 25; 910 - private boolean on = true; 911 - private boolean transmit = false; 912 - private DatagramSocket socket; 913 - private Rectangle area; 914 - private int tiles[][][]; 915 - private int maxI; 916 - private int maxJ; 917 - private ImageEncoder encoder; 918 - public final static int KEYFRAME = 10; 919 - 920 - public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) { 921 - 922 - try { 923 - robot = new Robot(); 924 - 925 - maxI = (int) Math.ceil(area.getWidth() / tileWidth); 926 - maxJ = (int) Math.ceil(area.getHeight() / tileWidth); 927 - 928 - tiles = new int[maxI][maxJ][tileWidth * tileWidth]; 929 - 930 - this.area = area; 931 - this.socket = socket; 932 - localHost = socket.getLocalAddress(); 933 - localPort = socket.getLocalPort(); 934 - this.remoteHost = remoteHost; 935 - this.remotePort = remotePort; 936 - this.encoder = new DefaultEncoder(); 937 - 938 - transmit = true; 939 - 940 - } 941 - catch (AWTException e) { 942 - e.printStackTrace(); 943 - } 944 - 945 - } 946 - 947 - public void start() { 948 - byte buf[] = new byte[1024]; 949 - final DatagramPacket p = new DatagramPacket(buf, 1024); 950 - 951 - int keyframe = 0; 952 - 953 - while (on) { 954 - if (transmit) { 955 - 956 - BufferedImage capture = robot.createScreenCapture(area); 957 - 958 - QuantizeFilter filter = new QuantizeFilter(); 959 - capture = filter.filter(capture, null); 960 - 961 - long trace = System.currentTimeMillis(); 962 - 963 - if (++keyframe > KEYFRAME) { 964 - keyframe = 0; 965 - } 966 - LOGGER.debug("KEYFRAME:" + keyframe); 967 - 968 - for (int i = 0; i < maxI; i++) { 969 - for (int j = 0; j < maxJ; j++) { 970 - 971 - final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth); 972 - 973 - int pixels[] = new int[tileWidth * tileWidth]; 974 - 975 - PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth); 976 - 977 - try { 978 - if (pg.grabPixels()) { 979 - 980 - if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) { 981 - 982 - ByteArrayOutputStream baos = encoder.encode(bufferedImage); 983 - 984 - if (baos != null) { 985 - 986 - try { 987 - 988 - Thread.sleep(1); 989 - 990 - baos.write(i); 991 - baos.write(j); 992 - 993 - byte[] bytesOut = baos.toByteArray(); 994 - 995 - if (bytesOut.length > 1000) 996 - LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length); 997 - 998 - p.setData(bytesOut); 999 - p.setAddress(remoteHost); 1000 - p.setPort(remotePort); 1001 - 1002 - try { 1003 - socket.send(p); 1004 - } 1005 - catch (IOException e) { 1006 - e.printStackTrace(); 1007 - } 1008 - 1009 - tiles[i][j] = pixels; 1010 - 1011 - } 1012 - catch (Exception e) { 1013 - } 1014 - 1015 - } 1016 - 1017 - } 1018 - 1019 - } 1020 - } 1021 - catch (InterruptedException e) { 1022 - e.printStackTrace(); 1023 - } 1024 - } 1025 - } 1026 - 1027 - trace = (System.currentTimeMillis() - trace); 1028 - LOGGER.debug("Loop Time:" + trace); 1029 - 1030 - if (trace < 500) { 1031 - try { 1032 - Thread.sleep(500 - trace); 1033 - } 1034 - catch (InterruptedException e) { 1035 - e.printStackTrace(); 1036 - } 1037 - } 1038 - } 1039 - } 1040 - } 1041 - 1042 - public void run() { 1043 - start(); 1044 - } 1045 - 1046 - /** 1047 - * Set Transmit Enabled/Disabled 1048 - * 1049 - * @param transmit boolean Enabled/Disabled 1050 - */ 1051 - public void setTransmit(boolean transmit) { 1052 - this.transmit = transmit; 1053 - } 1054 - 1055 - /** 1056 - * Get the encoder used to encode Images Tiles 1057 - * 1058 - * @return encoder 1059 - */ 1060 - public ImageEncoder getEncoder() { 1061 - return encoder; 1062 - } 1063 - 1064 - /** 1065 - * Set the encoder used to encode Image Tiles 1066 - * 1067 - * @param encoder encoder 1068 - */ 1069 - public void setEncoder(ImageEncoder encoder) { 1070 - this.encoder = encoder; 1071 - } 1072 - 1073 - /** 1074 - * Stops Transmitter 1075 - */ 1076 - public void stop() { 1077 - this.transmit = false; 1078 - this.on = false; 1079 - socket.close(); 1080 - } 1081 -} 1082 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java 1083 =================================================================== 1084 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (revision 11644) 1085 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (working copy) 1086 @@ -1,13 +0,0 @@ 1087 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1088 - 1089 -import java.awt.image.BufferedImage; 1090 -import java.io.ByteArrayOutputStream; 1091 - 1092 -/** 1093 - * Image Encoder Interface use this interface if you want to change the default encoder 1094 - * 1095 - * @author Thiago Rocha Camargo 1096 - */ 1097 -public interface ImageEncoder { 1098 - public ByteArrayOutputStream encode(BufferedImage bufferedImage); 1099 -} 1100 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java 1101 =================================================================== 1102 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (revision 11644) 1103 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (working copy) 1104 @@ -1,223 +0,0 @@ 1105 -/* 1106 -Copyright 2006 Jerry Huxtable 1107 - 1108 -Licensed under the Apache License, Version 2.0 (the "License"); 1109 -you may not use this file except in compliance with the License. 1110 -You may obtain a copy of the License at 1111 - 1112 - http://www.apache.org/licenses/LICENSE-2.0 1113 - 1114 -Unless required by applicable law or agreed to in writing, software 1115 -distributed under the License is distributed on an "AS IS" BASIS, 1116 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1117 -See the License for the specific language governing permissions and 1118 -limitations under the License. 1119 -*/ 1120 - 1121 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1122 - 1123 -import java.awt.*; 1124 -import java.util.Random; 1125 - 1126 -/** 1127 - * Some more useful math functions for image processing. 1128 - * These are becoming obsolete as we move to Java2D. Use MiscComposite instead. 1129 - */ 1130 -public class PixelUtils { 1131 - 1132 - public final static int REPLACE = 0; 1133 - public final static int NORMAL = 1; 1134 - public final static int MIN = 2; 1135 - public final static int MAX = 3; 1136 - public final static int ADD = 4; 1137 - public final static int SUBTRACT = 5; 1138 - public final static int DIFFERENCE = 6; 1139 - public final static int MULTIPLY = 7; 1140 - public final static int HUE = 8; 1141 - public final static int SATURATION = 9; 1142 - public final static int VALUE = 10; 1143 - public final static int COLOR = 11; 1144 - public final static int SCREEN = 12; 1145 - public final static int AVERAGE = 13; 1146 - public final static int OVERLAY = 14; 1147 - public final static int CLEAR = 15; 1148 - public final static int EXCHANGE = 16; 1149 - public final static int DISSOLVE = 17; 1150 - public final static int DST_IN = 18; 1151 - public final static int ALPHA = 19; 1152 - public final static int ALPHA_TO_GRAY = 20; 1153 - 1154 - private static Random randomGenerator = new Random(); 1155 - 1156 - /** 1157 - * Clamp a value to the range 0..255 1158 - */ 1159 - public static int clamp(int c) { 1160 - if (c < 0) 1161 - return 0; 1162 - if (c > 255) 1163 - return 255; 1164 - return c; 1165 - } 1166 - 1167 - public static int interpolate(int v1, int v2, float f) { 1168 - return clamp((int)(v1+f*(v2-v1))); 1169 - } 1170 - 1171 - public static int brightness(int rgb) { 1172 - int r = (rgb >> 16) & 0xff; 1173 - int g = (rgb >> 8) & 0xff; 1174 - int b = rgb & 0xff; 1175 - return (r+g+b)/3; 1176 - } 1177 - 1178 - public static boolean nearColors(int rgb1, int rgb2, int tolerance) { 1179 - int r1 = (rgb1 >> 16) & 0xff; 1180 - int g1 = (rgb1 >> 8) & 0xff; 1181 - int b1 = rgb1 & 0xff; 1182 - int r2 = (rgb2 >> 16) & 0xff; 1183 - int g2 = (rgb2 >> 8) & 0xff; 1184 - int b2 = rgb2 & 0xff; 1185 - return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; 1186 - } 1187 - 1188 - private final static float hsb1[] = new float[3];//FIXME-not thread safe 1189 - private final static float hsb2[] = new float[3];//FIXME-not thread safe 1190 - 1191 - // Return rgb1 painted onto rgb2 1192 - public static int combinePixels(int rgb1, int rgb2, int op) { 1193 - return combinePixels(rgb1, rgb2, op, 0xff); 1194 - } 1195 - 1196 - public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { 1197 - return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); 1198 - } 1199 - 1200 - public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { 1201 - if (op == REPLACE) 1202 - return rgb1; 1203 - int a1 = (rgb1 >> 24) & 0xff; 1204 - int r1 = (rgb1 >> 16) & 0xff; 1205 - int g1 = (rgb1 >> 8) & 0xff; 1206 - int b1 = rgb1 & 0xff; 1207 - int a2 = (rgb2 >> 24) & 0xff; 1208 - int r2 = (rgb2 >> 16) & 0xff; 1209 - int g2 = (rgb2 >> 8) & 0xff; 1210 - int b2 = rgb2 & 0xff; 1211 - 1212 - switch (op) { 1213 - case NORMAL: 1214 - break; 1215 - case MIN: 1216 - r1 = Math.min(r1, r2); 1217 - g1 = Math.min(g1, g2); 1218 - b1 = Math.min(b1, b2); 1219 - break; 1220 - case MAX: 1221 - r1 = Math.max(r1, r2); 1222 - g1 = Math.max(g1, g2); 1223 - b1 = Math.max(b1, b2); 1224 - break; 1225 - case ADD: 1226 - r1 = clamp(r1+r2); 1227 - g1 = clamp(g1+g2); 1228 - b1 = clamp(b1+b2); 1229 - break; 1230 - case SUBTRACT: 1231 - r1 = clamp(r2-r1); 1232 - g1 = clamp(g2-g1); 1233 - b1 = clamp(b2-b1); 1234 - break; 1235 - case DIFFERENCE: 1236 - r1 = clamp(Math.abs(r1-r2)); 1237 - g1 = clamp(Math.abs(g1-g2)); 1238 - b1 = clamp(Math.abs(b1-b2)); 1239 - break; 1240 - case MULTIPLY: 1241 - r1 = clamp(r1*r2/255); 1242 - g1 = clamp(g1*g2/255); 1243 - b1 = clamp(b1*b2/255); 1244 - break; 1245 - case DISSOLVE: 1246 - if ((randomGenerator.nextInt() & 0xff) <= a1) { 1247 - r1 = r2; 1248 - g1 = g2; 1249 - b1 = b2; 1250 - } 1251 - break; 1252 - case AVERAGE: 1253 - r1 = (r1+r2)/2; 1254 - g1 = (g1+g2)/2; 1255 - b1 = (b1+b2)/2; 1256 - break; 1257 - case HUE: 1258 - case SATURATION: 1259 - case VALUE: 1260 - case COLOR: 1261 - Color.RGBtoHSB(r1, g1, b1, hsb1); 1262 - Color.RGBtoHSB(r2, g2, b2, hsb2); 1263 - switch (op) { 1264 - case HUE: 1265 - hsb2[0] = hsb1[0]; 1266 - break; 1267 - case SATURATION: 1268 - hsb2[1] = hsb1[1]; 1269 - break; 1270 - case VALUE: 1271 - hsb2[2] = hsb1[2]; 1272 - break; 1273 - case COLOR: 1274 - hsb2[0] = hsb1[0]; 1275 - hsb2[1] = hsb1[1]; 1276 - break; 1277 - } 1278 - rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); 1279 - r1 = (rgb1 >> 16) & 0xff; 1280 - g1 = (rgb1 >> 8) & 0xff; 1281 - b1 = rgb1 & 0xff; 1282 - break; 1283 - case SCREEN: 1284 - r1 = 255 - ((255 - r1) * (255 - r2)) / 255; 1285 - g1 = 255 - ((255 - g1) * (255 - g2)) / 255; 1286 - b1 = 255 - ((255 - b1) * (255 - b2)) / 255; 1287 - break; 1288 - case OVERLAY: 1289 - int m, s; 1290 - s = 255 - ((255 - r1) * (255 - r2)) / 255; 1291 - m = r1 * r2 / 255; 1292 - r1 = (s * r1 + m * (255 - r1)) / 255; 1293 - s = 255 - ((255 - g1) * (255 - g2)) / 255; 1294 - m = g1 * g2 / 255; 1295 - g1 = (s * g1 + m * (255 - g1)) / 255; 1296 - s = 255 - ((255 - b1) * (255 - b2)) / 255; 1297 - m = b1 * b2 / 255; 1298 - b1 = (s * b1 + m * (255 - b1)) / 255; 1299 - break; 1300 - case CLEAR: 1301 - r1 = g1 = b1 = 0xff; 1302 - break; 1303 - case DST_IN: 1304 - r1 = clamp((r2*a1)/255); 1305 - g1 = clamp((g2*a1)/255); 1306 - b1 = clamp((b2*a1)/255); 1307 - a1 = clamp((a2*a1)/255); 1308 - return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 1309 - case ALPHA: 1310 - a1 = a1*a2/255; 1311 - return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; 1312 - case ALPHA_TO_GRAY: 1313 - int na = 255-a1; 1314 - return (a1 << 24) | (na << 16) | (na << 8) | na; 1315 - } 1316 - if (extraAlpha != 0xff || a1 != 0xff) { 1317 - a1 = a1*extraAlpha/255; 1318 - int a3 = (255-a1)*a2/255; 1319 - r1 = clamp((r1*a1+r2*a3)/255); 1320 - g1 = clamp((g1*a1+g2*a3)/255); 1321 - b1 = clamp((b1*a1+b2*a3)/255); 1322 - a1 = clamp(a1+a3); 1323 - } 1324 - return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 1325 - } 1326 - 1327 -} 1328 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java 1329 =================================================================== 1330 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (revision 11644) 1331 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (working copy) 1332 @@ -1,53 +0,0 @@ 1333 -/* 1334 -Copyright 2006 Jerry Huxtable 1335 - 1336 -Licensed under the Apache License, Version 2.0 (the "License"); 1337 -you may not use this file except in compliance with the License. 1338 -You may obtain a copy of the License at 1339 - 1340 - http://www.apache.org/licenses/LICENSE-2.0 1341 - 1342 -Unless required by applicable law or agreed to in writing, software 1343 -distributed under the License is distributed on an "AS IS" BASIS, 1344 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1345 -See the License for the specific language governing permissions and 1346 -limitations under the License. 1347 -*/ 1348 - 1349 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1350 - 1351 -/** 1352 - * The interface for an image quantizer. The addColor method is called (repeatedly 1353 - * if necessary) with all the image pixels. A color table can then be returned by 1354 - * calling the buildColorTable method. 1355 - */ 1356 -public interface Quantizer { 1357 - /** 1358 - * Initialize the quantizer. This should be called before adding any pixels. 1359 - * @param numColors the number of colors we're quantizing to. 1360 - */ 1361 - public void setup(int numColors); 1362 - 1363 - /** 1364 - * Add pixels to the quantizer. 1365 - * @param pixels the array of ARGB pixels 1366 - * @param offset the offset into the array 1367 - * @param count the count of pixels 1368 - */ 1369 - public void addPixels(int[] pixels, int offset, int count); 1370 - 1371 - /** 1372 - * Build a color table from the added pixels. 1373 - * @return an array of ARGB pixels representing a color table 1374 - */ 1375 - public int[] buildColorTable(); 1376 - 1377 - /** 1378 - * Using the previously-built color table, return the index into that table for a pixel. 1379 - * This is guaranteed to return a valid index - returning the index of a color closer 1380 - * to that requested if necessary. 1381 - * @param rgb the pixel to find 1382 - * @return the pixel's index in the color table 1383 - */ 1384 - public int getIndexForColor(int rgb); 1385 -} 1386 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java 1387 =================================================================== 1388 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (revision 11644) 1389 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (working copy) 1390 @@ -1,24 +0,0 @@ 1391 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1392 - 1393 -import javax.imageio.ImageIO; 1394 -import java.awt.image.BufferedImage; 1395 -import java.io.ByteArrayOutputStream; 1396 -import java.io.IOException; 1397 - 1398 -/** 1399 - * Implements a default PNG Encoder 1400 - */ 1401 -public class DefaultEncoder implements ImageEncoder{ 1402 - 1403 - public ByteArrayOutputStream encode(BufferedImage bufferedImage) { 1404 - ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1405 - try { 1406 - ImageIO.write(bufferedImage, "png", baos); 1407 - } 1408 - catch (IOException e) { 1409 - e.printStackTrace(); 1410 - baos = null; 1411 - } 1412 - return baos; 1413 - } 1414 -} 1415 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java 1416 =================================================================== 1417 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (revision 11644) 1418 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (working copy) 1419 @@ -1,178 +0,0 @@ 1420 -/* 1421 -Copyright 2006 Jerry Huxtable 1422 - 1423 -Licensed under the Apache License, Version 2.0 (the "License"); 1424 -you may not use this file except in compliance with the License. 1425 -You may obtain a copy of the License at 1426 - 1427 - http://www.apache.org/licenses/LICENSE-2.0 1428 - 1429 -Unless required by applicable law or agreed to in writing, software 1430 -distributed under the License is distributed on an "AS IS" BASIS, 1431 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1432 -See the License for the specific language governing permissions and 1433 -limitations under the License. 1434 -*/ 1435 - 1436 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1437 - 1438 -import java.awt.*; 1439 - 1440 -/** 1441 - * A filter which quantizes an image to a set number of colors - useful for producing 1442 - * images which are to be encoded using an index color model. The filter can perform 1443 - * Floyd-Steinberg error-diffusion dithering if required. At present, the quantization 1444 - * is done using an octtree algorithm but I eventually hope to add more quantization 1445 - * methods such as median cut. Note: at present, the filter produces an image which 1446 - * uses the RGB color model (because the application it was written for required it). 1447 - * I hope to extend it to produce an IndexColorModel by request. 1448 - */ 1449 -public class QuantizeFilter extends WholeImageFilter { 1450 - 1451 - /** 1452 - * Floyd-Steinberg dithering matrix. 1453 - */ 1454 - protected final static int[] matrix = { 1455 - 0, 0, 0, 1456 - 0, 0, 7, 1457 - 3, 5, 1, 1458 - }; 1459 - private int sum = 3+5+7+1; 1460 - 1461 - private boolean dither; 1462 - private int numColors = 256; 1463 - private boolean serpentine = true; 1464 - 1465 - /** 1466 - * Set the number of colors to quantize to. 1467 - * @param numColors the number of colors. The default is 256. 1468 - */ 1469 - public void setNumColors(int numColors) { 1470 - this.numColors = Math.min(Math.max(numColors, 8), 256); 1471 - } 1472 - 1473 - /** 1474 - * Get the number of colors to quantize to. 1475 - * @return the number of colors. 1476 - */ 1477 - public int getNumColors() { 1478 - return numColors; 1479 - } 1480 - 1481 - /** 1482 - * Set whether to use dithering or not. If not, the image is posterized. 1483 - * @param dither true to use dithering 1484 - */ 1485 - public void setDither(boolean dither) { 1486 - this.dither = dither; 1487 - } 1488 - 1489 - /** 1490 - * Return the dithering setting 1491 - * @return the current setting 1492 - */ 1493 - public boolean getDither() { 1494 - return dither; 1495 - } 1496 - 1497 - /** 1498 - * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output. 1499 - * @param serpentine true to use serpentine pattern 1500 - */ 1501 - public void setSerpentine(boolean serpentine) { 1502 - this.serpentine = serpentine; 1503 - } 1504 - 1505 - /** 1506 - * Return the serpentine setting 1507 - * @return the current setting 1508 - */ 1509 - public boolean getSerpentine() { 1510 - return serpentine; 1511 - } 1512 - 1513 - public void quantize(int[] inPixels, int[] outPixels, int width, int height, int numColors, boolean dither, boolean serpentine) { 1514 - int count = width*height; 1515 - Quantizer quantizer = new OctTreeQuantizer(); 1516 - quantizer.setup(numColors); 1517 - quantizer.addPixels(inPixels, 0, count); 1518 - int[] table = quantizer.buildColorTable(); 1519 - 1520 - if (!dither) { 1521 - for (int i = 0; i < count; i++) 1522 - outPixels[i] = table[quantizer.getIndexForColor(inPixels[i])]; 1523 - } else { 1524 - int index = 0; 1525 - for (int y = 0; y < height; y++) { 1526 - boolean reverse = serpentine && (y & 1) == 1; 1527 - int direction; 1528 - if (reverse) { 1529 - index = y*width+width-1; 1530 - direction = -1; 1531 - } else { 1532 - index = y*width; 1533 - direction = 1; 1534 - } 1535 - for (int x = 0; x < width; x++) { 1536 - int rgb1 = inPixels[index]; 1537 - int rgb2 = table[quantizer.getIndexForColor(rgb1)]; 1538 - 1539 - outPixels[index] = rgb2; 1540 - 1541 - int r1 = (rgb1 >> 16) & 0xff; 1542 - int g1 = (rgb1 >> 8) & 0xff; 1543 - int b1 = rgb1 & 0xff; 1544 - 1545 - int r2 = (rgb2 >> 16) & 0xff; 1546 - int g2 = (rgb2 >> 8) & 0xff; 1547 - int b2 = rgb2 & 0xff; 1548 - 1549 - int er = r1-r2; 1550 - int eg = g1-g2; 1551 - int eb = b1-b2; 1552 - 1553 - for (int i = -1; i <= 1; i++) { 1554 - int iy = i+y; 1555 - if (0 <= iy && iy < height) { 1556 - for (int j = -1; j <= 1; j++) { 1557 - int jx = j+x; 1558 - if (0 <= jx && jx < width) { 1559 - int w; 1560 - if (reverse) 1561 - w = matrix[(i+1)*3-j+1]; 1562 - else 1563 - w = matrix[(i+1)*3+j+1]; 1564 - if (w != 0) { 1565 - int k = reverse ? index - j : index + j; 1566 - rgb1 = inPixels[k]; 1567 - r1 = (rgb1 >> 16) & 0xff; 1568 - g1 = (rgb1 >> 8) & 0xff; 1569 - b1 = rgb1 & 0xff; 1570 - r1 += er * w/sum; 1571 - g1 += eg * w/sum; 1572 - b1 += eb * w/sum; 1573 - inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1); 1574 - } 1575 - } 1576 - } 1577 - } 1578 - } 1579 - index += direction; 1580 - } 1581 - } 1582 - } 1583 - } 1584 - 1585 - protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 1586 - int[] outPixels = new int[width*height]; 1587 - 1588 - quantize(inPixels, outPixels, width, height, numColors, dither, serpentine); 1589 - 1590 - return outPixels; 1591 - } 1592 - 1593 - public String toString() { 1594 - return "Colors/Quantize..."; 1595 - } 1596 - 1597 -} 1598 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java 1599 =================================================================== 1600 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (revision 11644) 1601 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (working copy) 1602 @@ -1,150 +0,0 @@ 1603 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1604 - 1605 -import java.awt.*; 1606 -import java.awt.image.BufferedImage; 1607 -import java.io.ByteArrayInputStream; 1608 -import java.io.IOException; 1609 -import java.net.DatagramPacket; 1610 -import java.net.DatagramSocket; 1611 -import java.net.InetAddress; 1612 -import java.net.SocketException; 1613 - 1614 -/** 1615 - * UDP Image Receiver. 1616 - * It uses PNG Tiles into UDP packets. 1617 - * 1618 - * @author Thiago Rocha Camargo 1619 - */ 1620 -public class ImageReceiver extends Canvas { 1621 - 1622 - private boolean on = true; 1623 - private DatagramSocket socket; 1624 - private BufferedImage tiles[][]; 1625 - private static final int tileWidth = ImageTransmitter.tileWidth; 1626 - private InetAddress localHost; 1627 - private InetAddress remoteHost; 1628 - private int localPort; 1629 - private int remotePort; 1630 - private ImageDecoder decoder; 1631 - 1632 - public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) { 1633 - tiles = new BufferedImage[width][height]; 1634 - 1635 - try { 1636 - 1637 - socket = new DatagramSocket(localPort); 1638 - localHost = socket.getLocalAddress(); 1639 - this.remoteHost = remoteHost; 1640 - this.remotePort = remotePort; 1641 - this.localPort = localPort; 1642 - this.decoder = new DefaultDecoder(); 1643 - 1644 - new Thread(new Runnable() { 1645 - public void run() { 1646 - byte buf[] = new byte[1024]; 1647 - DatagramPacket p = new DatagramPacket(buf, 1024); 1648 - try { 1649 - while (on) { 1650 - socket.receive(p); 1651 - 1652 - int length = p.getLength(); 1653 - 1654 - BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2)); 1655 - 1656 - if (bufferedImage != null) { 1657 - 1658 - int x = p.getData()[length - 2]; 1659 - int y = p.getData()[length - 1]; 1660 - 1661 - drawTile(x, y, bufferedImage); 1662 - 1663 - } 1664 - 1665 - } 1666 - } 1667 - catch (IOException e) { 1668 - e.printStackTrace(); 1669 - } 1670 - } 1671 - }).start(); 1672 - 1673 - new Thread(new Runnable() { 1674 - public void run() { 1675 - byte buf[] = new byte[1024]; 1676 - DatagramPacket p = new DatagramPacket(buf, 1024); 1677 - try { 1678 - while (on) { 1679 - 1680 - p.setAddress(remoteHost); 1681 - p.setPort(remotePort); 1682 - socket.send(p); 1683 - 1684 - try { 1685 - Thread.sleep(1000); 1686 - } 1687 - catch (InterruptedException e) { 1688 - e.printStackTrace(); 1689 - } 1690 - 1691 - } 1692 - } 1693 - catch (IOException e) { 1694 - e.printStackTrace(); 1695 - } 1696 - } 1697 - }).start(); 1698 - 1699 - } 1700 - catch (SocketException e) { 1701 - e.printStackTrace(); 1702 - } 1703 - this.setSize(width, height); 1704 - } 1705 - 1706 - public InetAddress getLocalHost() { 1707 - return localHost; 1708 - } 1709 - 1710 - public InetAddress getRemoteHost() { 1711 - return remoteHost; 1712 - } 1713 - 1714 - public int getLocalPort() { 1715 - return localPort; 1716 - } 1717 - 1718 - public int getRemotePort() { 1719 - return remotePort; 1720 - } 1721 - 1722 - public DatagramSocket getDatagramSocket() { 1723 - return socket; 1724 - } 1725 - 1726 - public void drawTile(int x, int y, BufferedImage bufferedImage) { 1727 - tiles[x][y] = bufferedImage; 1728 - //repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth); 1729 - this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this); 1730 - } 1731 - 1732 - public void paint(Graphics g) { 1733 - for (int i = 0; i < tiles.length; i++) { 1734 - for (int j = 0; j < tiles[0].length; j++) { 1735 - g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this); 1736 - } 1737 - } 1738 - } 1739 - 1740 - public ImageDecoder getDecoder() { 1741 - return decoder; 1742 - } 1743 - 1744 - public void setDecoder(ImageDecoder decoder) { 1745 - this.decoder = decoder; 1746 - } 1747 - 1748 - public void stop(){ 1749 - this.on=false; 1750 - socket.close(); 1751 - } 1752 -} 1753 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java 1754 =================================================================== 1755 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (revision 11644) 1756 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (working copy) 1757 @@ -1,86 +0,0 @@ 1758 -/* 1759 -Copyright 2006 Jerry Huxtable 1760 - 1761 -Licensed under the Apache License, Version 2.0 (the "License"); 1762 -you may not use this file except in compliance with the License. 1763 -You may obtain a copy of the License at 1764 - 1765 - http://www.apache.org/licenses/LICENSE-2.0 1766 - 1767 -Unless required by applicable law or agreed to in writing, software 1768 -distributed under the License is distributed on an "AS IS" BASIS, 1769 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1770 -See the License for the specific language governing permissions and 1771 -limitations under the License. 1772 -*/ 1773 - 1774 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1775 - 1776 -import java.awt.*; 1777 -import java.awt.image.BufferedImage; 1778 -import java.awt.image.ColorModel; 1779 -import java.awt.image.WritableRaster; 1780 - 1781 -/** 1782 - * A filter which acts as a superclass for filters which need to have the whole image in memory 1783 - * to do their stuff. 1784 - */ 1785 -public abstract class WholeImageFilter extends AbstractBufferedImageOp { 1786 - 1787 - /** 1788 - * The output image bounds. 1789 - */ 1790 - protected Rectangle transformedSpace; 1791 - 1792 - /** 1793 - * The input image bounds. 1794 - */ 1795 - protected Rectangle originalSpace; 1796 - 1797 - /** 1798 - * Construct a WholeImageFilter. 1799 - */ 1800 - public WholeImageFilter() { 1801 - } 1802 - 1803 - public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 1804 - int width = src.getWidth(); 1805 - int height = src.getHeight(); 1806 - int type = src.getType(); 1807 - WritableRaster srcRaster = src.getRaster(); 1808 - 1809 - originalSpace = new Rectangle(0, 0, width, height); 1810 - transformedSpace = new Rectangle(0, 0, width, height); 1811 - transformSpace(transformedSpace); 1812 - 1813 - if ( dst == null ) { 1814 - ColorModel dstCM = src.getColorModel(); 1815 - dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null); 1816 - } 1817 - WritableRaster dstRaster = dst.getRaster(); 1818 - 1819 - int[] inPixels = getRGB( src, 0, 0, width, height, null ); 1820 - inPixels = filterPixels( width, height, inPixels, transformedSpace ); 1821 - setRGB( dst, 0, 0, transformedSpace.width, transformedSpace.height, inPixels ); 1822 - 1823 - return dst; 1824 - } 1825 - 1826 - /** 1827 - * Calculate output bounds for given input bounds. 1828 - * @param rect input and output rectangle 1829 - */ 1830 - protected void transformSpace(Rectangle rect) { 1831 - } 1832 - 1833 - /** 1834 - * Actually filter the pixels. 1835 - * @param width the image width 1836 - * @param height the image height 1837 - * @param inPixels the image pixels 1838 - * @param transformedSpace the output bounds 1839 - * @return the output pixels 1840 - */ 1841 - protected abstract int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ); 1842 -} 1843 - 1844 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java 1845 =================================================================== 1846 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (revision 11644) 1847 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (working copy) 1848 @@ -1,98 +0,0 @@ 1849 -/* 1850 -Copyright 2006 Jerry Huxtable 1851 - 1852 -Licensed under the Apache License, Version 2.0 (the "License"); 1853 -you may not use this file except in compliance with the License. 1854 -You may obtain a copy of the License at 1855 - 1856 - http://www.apache.org/licenses/LICENSE-2.0 1857 - 1858 -Unless required by applicable law or agreed to in writing, software 1859 -distributed under the License is distributed on an "AS IS" BASIS, 1860 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1861 -See the License for the specific language governing permissions and 1862 -limitations under the License. 1863 -*/ 1864 - 1865 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1866 - 1867 -import java.awt.*; 1868 -import java.awt.geom.Point2D; 1869 -import java.awt.geom.Rectangle2D; 1870 -import java.awt.image.BufferedImage; 1871 -import java.awt.image.BufferedImageOp; 1872 -import java.awt.image.ColorModel; 1873 - 1874 -/** 1875 - * A convenience class which implements those methods of BufferedImageOp which are rarely changed. 1876 - */ 1877 -public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable { 1878 - 1879 - public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { 1880 - if ( dstCM == null ) 1881 - dstCM = src.getColorModel(); 1882 - return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); 1883 - } 1884 - 1885 - public Rectangle2D getBounds2D( BufferedImage src ) { 1886 - return new Rectangle(0, 0, src.getWidth(), src.getHeight()); 1887 - } 1888 - 1889 - public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { 1890 - if ( dstPt == null ) 1891 - dstPt = new Point2D.Double(); 1892 - dstPt.setLocation( srcPt.getX(), srcPt.getY() ); 1893 - return dstPt; 1894 - } 1895 - 1896 - public RenderingHints getRenderingHints() { 1897 - return null; 1898 - } 1899 - 1900 - /** 1901 - * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance 1902 - * penalty of BufferedImage.getRGB unmanaging the image. 1903 - * @param image a BufferedImage object 1904 - * @param x the left edge of the pixel block 1905 - * @param y the right edge of the pixel block 1906 - * @param width the width of the pixel arry 1907 - * @param height the height of the pixel arry 1908 - * @param pixels the array to hold the returned pixels. May be null. 1909 - * @return the pixels 1910 - * @see #setRGB 1911 - */ 1912 - public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { 1913 - int type = image.getType(); 1914 - if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) 1915 - return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); 1916 - return image.getRGB( x, y, width, height, pixels, 0, width ); 1917 - } 1918 - 1919 - /** 1920 - * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance 1921 - * penalty of BufferedImage.setRGB unmanaging the image. 1922 - * @param image a BufferedImage object 1923 - * @param x the left edge of the pixel block 1924 - * @param y the right edge of the pixel block 1925 - * @param width the width of the pixel arry 1926 - * @param height the height of the pixel arry 1927 - * @param pixels the array of pixels to set 1928 - * @see #getRGB 1929 - */ 1930 - public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { 1931 - int type = image.getType(); 1932 - if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) 1933 - image.getRaster().setDataElements( x, y, width, height, pixels ); 1934 - else 1935 - image.setRGB( x, y, width, height, pixels, 0, width ); 1936 - } 1937 - 1938 - public Object clone() { 1939 - try { 1940 - return super.clone(); 1941 - } 1942 - catch ( CloneNotSupportedException e ) { 1943 - return null; 1944 - } 1945 - } 1946 -} 1947 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java 1948 =================================================================== 1949 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (revision 11644) 1950 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (working copy) 1951 @@ -1,15 +0,0 @@ 1952 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1953 - 1954 -import java.awt.image.BufferedImage; 1955 -import java.io.ByteArrayInputStream; 1956 -import java.io.IOException; 1957 - 1958 -/** 1959 - * Image Decoder Interface use this interface if you want to change the default decoder 1960 - * 1961 - * @author Thiago Rocha Camargo 1962 - */ 1963 -public interface ImageDecoder { 1964 - 1965 - public BufferedImage decode(ByteArrayInputStream stream) throws IOException; 1966 -} 1967 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java 1968 =================================================================== 1969 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (revision 11644) 1970 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (working copy) 1971 @@ -1,287 +0,0 @@ 1972 -/* 1973 -Copyright 2006 Jerry Huxtable 1974 - 1975 -Licensed under the Apache License, Version 2.0 (the "License"); 1976 -you may not use this file except in compliance with the License. 1977 -You may obtain a copy of the License at 1978 - 1979 - http://www.apache.org/licenses/LICENSE-2.0 1980 - 1981 -Unless required by applicable law or agreed to in writing, software 1982 -distributed under the License is distributed on an "AS IS" BASIS, 1983 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1984 -See the License for the specific language governing permissions and 1985 -limitations under the License. 1986 -*/ 1987 - 1988 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 1989 - 1990 -import java.io.PrintStream; 1991 -import java.util.Vector; 1992 - 1993 -import org.jivesoftware.smackx.jingle.SmackLogger; 1994 - 1995 -/** 1996 - * An image Quantizer based on the Octree algorithm. This is a very basic implementation 1997 - * at present and could be much improved by picking the nodes to reduce more carefully 1998 - * (i.e. not completely at random) when I get the time. 1999 - */ 2000 -public class OctTreeQuantizer implements Quantizer { 2001 - 2002 - private static final SmackLogger LOGGER = SmackLogger.getLogger(OctTreeQuantizer.class); 2003 - 2004 - /** 2005 - * The greatest depth the tree is allowed to reach 2006 - */ 2007 - final static int MAX_LEVEL = 5; 2008 - 2009 - /** 2010 - * An Octtree node. 2011 - */ 2012 - class OctTreeNode { 2013 - int children; 2014 - int level; 2015 - OctTreeNode parent; 2016 - OctTreeNode leaf[] = new OctTreeNode[8]; 2017 - boolean isLeaf; 2018 - int count; 2019 - int totalRed; 2020 - int totalGreen; 2021 - int totalBlue; 2022 - int index; 2023 - 2024 - /** 2025 - * A debugging method which prints the tree out. 2026 - */ 2027 - public void list(PrintStream s, int level) { 2028 - String indentStr = ""; 2029 - for (int i = 0; i < level; i++) 2030 - indentStr += " "; 2031 - if (count == 0) 2032 - LOGGER.debug(indentStr + index + ": count=" + count); 2033 - else 2034 - LOGGER.debug(indentStr + index + ": count=" + count + " red=" + (totalRed/count) + " green=" + (totalGreen / count) + " blue=" + (totalBlue / count)); 2035 - for (int i = 0; i < 8; i++) 2036 - if (leaf[i] != null) 2037 - leaf[i].list(s, level+2); 2038 - } 2039 - } 2040 - 2041 - private int nodes = 0; 2042 - private OctTreeNode root; 2043 - private int reduceColors; 2044 - private int maximumColors; 2045 - private int colors = 0; 2046 - private Vector[] colorList; 2047 - 2048 - public OctTreeQuantizer() { 2049 - setup(256); 2050 - colorList = new Vector[MAX_LEVEL+1]; 2051 - for (int i = 0; i < MAX_LEVEL+1; i++) 2052 - colorList[i] = new Vector(); 2053 - root = new OctTreeNode(); 2054 - } 2055 - 2056 - /** 2057 - * Initialize the quantizer. This should be called before adding any pixels. 2058 - * @param numColors the number of colors we're quantizing to. 2059 - */ 2060 - public void setup(int numColors) { 2061 - maximumColors = numColors; 2062 - reduceColors = Math.max(512, numColors * 2); 2063 - } 2064 - 2065 - /** 2066 - * Add pixels to the quantizer. 2067 - * @param pixels the array of ARGB pixels 2068 - * @param offset the offset into the array 2069 - * @param count the count of pixels 2070 - */ 2071 - public void addPixels(int[] pixels, int offset, int count) { 2072 - for (int i = 0; i < count; i++) { 2073 - insertColor(pixels[i+offset]); 2074 - if (colors > reduceColors) 2075 - reduceTree(reduceColors); 2076 - } 2077 - } 2078 - 2079 - /** 2080 - * Get the color table index for a color. 2081 - * @param rgb the color 2082 - * @return the index 2083 - */ 2084 - public int getIndexForColor(int rgb) { 2085 - int red = (rgb >> 16) & 0xff; 2086 - int green = (rgb >> 8) & 0xff; 2087 - int blue = rgb & 0xff; 2088 - 2089 - OctTreeNode node = root; 2090 - 2091 - for (int level = 0; level <= MAX_LEVEL; level++) { 2092 - OctTreeNode child; 2093 - int bit = 0x80 >> level; 2094 - 2095 - int index = 0; 2096 - if ((red & bit) != 0) 2097 - index += 4; 2098 - if ((green & bit) != 0) 2099 - index += 2; 2100 - if ((blue & bit) != 0) 2101 - index += 1; 2102 - 2103 - child = node.leaf[index]; 2104 - 2105 - if (child == null) 2106 - return node.index; 2107 - else if (child.isLeaf) 2108 - return child.index; 2109 - else 2110 - node = child; 2111 - } 2112 - LOGGER.debug("getIndexForColor failed"); 2113 - return 0; 2114 - } 2115 - 2116 - private void insertColor(int rgb) { 2117 - int red = (rgb >> 16) & 0xff; 2118 - int green = (rgb >> 8) & 0xff; 2119 - int blue = rgb & 0xff; 2120 - 2121 - OctTreeNode node = root; 2122 - 2123 -// LOGGER.debug("insertColor="+Integer.toHexString(rgb)); 2124 - for (int level = 0; level <= MAX_LEVEL; level++) { 2125 - OctTreeNode child; 2126 - int bit = 0x80 >> level; 2127 - 2128 - int index = 0; 2129 - if ((red & bit) != 0) 2130 - index += 4; 2131 - if ((green & bit) != 0) 2132 - index += 2; 2133 - if ((blue & bit) != 0) 2134 - index += 1; 2135 - 2136 - child = node.leaf[index]; 2137 - 2138 - if (child == null) { 2139 - node.children++; 2140 - 2141 - child = new OctTreeNode(); 2142 - child.parent = node; 2143 - node.leaf[index] = child; 2144 - node.isLeaf = false; 2145 - nodes++; 2146 - colorList[level].addElement(child); 2147 - 2148 - if (level == MAX_LEVEL) { 2149 - child.isLeaf = true; 2150 - child.count = 1; 2151 - child.totalRed = red; 2152 - child.totalGreen = green; 2153 - child.totalBlue = blue; 2154 - child.level = level; 2155 - colors++; 2156 - return; 2157 - } 2158 - 2159 - node = child; 2160 - } else if (child.isLeaf) { 2161 - child.count++; 2162 - child.totalRed += red; 2163 - child.totalGreen += green; 2164 - child.totalBlue += blue; 2165 - return; 2166 - } else 2167 - node = child; 2168 - } 2169 - LOGGER.debug("insertColor failed"); 2170 - } 2171 - 2172 - private void reduceTree(int numColors) { 2173 - for (int level = MAX_LEVEL-1; level >= 0; level--) { 2174 - Vector v = colorList[level]; 2175 - if (v != null && v.size() > 0) { 2176 - for (int j = 0; j < v.size(); j++) { 2177 - OctTreeNode node = (OctTreeNode)v.elementAt(j); 2178 - if (node.children > 0) { 2179 - for (int i = 0; i < 8; i++) { 2180 - OctTreeNode child = node.leaf[i]; 2181 - if (child != null) { 2182 - if (!child.isLeaf) 2183 - LOGGER.debug("not a leaf!"); 2184 - node.count += child.count; 2185 - node.totalRed += child.totalRed; 2186 - node.totalGreen += child.totalGreen; 2187 - node.totalBlue += child.totalBlue; 2188 - node.leaf[i] = null; 2189 - node.children--; 2190 - colors--; 2191 - nodes--; 2192 - colorList[level+1].removeElement(child); 2193 - } 2194 - } 2195 - node.isLeaf = true; 2196 - colors++; 2197 - if (colors <= numColors) 2198 - return; 2199 - } 2200 - } 2201 - } 2202 - } 2203 - 2204 - LOGGER.debug("Unable to reduce the OctTree"); 2205 - } 2206 - 2207 - /** 2208 - * Build the color table. 2209 - * @return the color table 2210 - */ 2211 - public int[] buildColorTable() { 2212 - int[] table = new int[colors]; 2213 - buildColorTable(root, table, 0); 2214 - return table; 2215 - } 2216 - 2217 - /** 2218 - * A quick way to use the quantizer. Just create a table the right size and pass in the pixels. 2219 - * @param inPixels the input colors 2220 - * @param table the output color table 2221 - */ 2222 - public void buildColorTable(int[] inPixels, int[] table) { 2223 - int count = inPixels.length; 2224 - maximumColors = table.length; 2225 - for (int i = 0; i < count; i++) { 2226 - insertColor(inPixels[i]); 2227 - if (colors > reduceColors) 2228 - reduceTree(reduceColors); 2229 - } 2230 - if (colors > maximumColors) 2231 - reduceTree(maximumColors); 2232 - buildColorTable(root, table, 0); 2233 - } 2234 - 2235 - private int buildColorTable(OctTreeNode node, int[] table, int index) { 2236 - if (colors > maximumColors) 2237 - reduceTree(maximumColors); 2238 - 2239 - if (node.isLeaf) { 2240 - int count = node.count; 2241 - table[index] = 0xff000000 | 2242 - ((node.totalRed/count) << 16) | 2243 - ((node.totalGreen/count) << 8) | 2244 - node.totalBlue/count; 2245 - node.index = index++; 2246 - } else { 2247 - for (int i = 0; i < 8; i++) { 2248 - if (node.leaf[i] != null) { 2249 - node.index = index; 2250 - index = buildColorTable(node.leaf[i], table, index); 2251 - } 2252 - } 2253 - } 2254 - return index; 2255 - } 2256 - 2257 -} 2258 - 2259 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java 2260 =================================================================== 2261 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (revision 11644) 2262 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (working copy) 2263 @@ -1,16 +0,0 @@ 2264 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api; 2265 - 2266 -import javax.imageio.ImageIO; 2267 -import java.awt.image.BufferedImage; 2268 -import java.io.ByteArrayInputStream; 2269 -import java.io.IOException; 2270 - 2271 -/** 2272 - * Implements a default PNG decoder. 2273 - */ 2274 -public class DefaultDecoder implements ImageDecoder { 2275 - 2276 - public BufferedImage decode(ByteArrayInputStream stream) throws IOException { 2277 - return ImageIO.read(stream); 2278 - } 2279 -} 2280 Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java 2281 =================================================================== 2282 --- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (revision 11644) 2283 +++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (working copy) 2284 @@ -1,115 +0,0 @@ 2285 -/** 2286 - * $RCSfile: ScreenShareMediaManager.java,v $ 2287 - * $Revision: 1.3 $ 2288 - * $Date: 25/12/2006 2289 - * <p/> 2290 - * Copyright 2003-2006 Jive Software. 2291 - * <p/> 2292 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 2293 - * you may not use this file except in compliance with the License. 2294 - * You may obtain a copy of the License at 2295 - * <p/> 2296 - * http://www.apache.org/licenses/LICENSE-2.0 2297 - * <p/> 2298 - * Unless required by applicable law or agreed to in writing, software 2299 - * distributed under the License is distributed on an "AS IS" BASIS, 2300 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2301 - * See the License for the specific language governing permissions and 2302 - * limitations under the License. 2303 - */ 2304 - 2305 -package org.jivesoftware.smackx.jingle.mediaimpl.sshare; 2306 - 2307 -import org.jivesoftware.smackx.jingle.JingleSession; 2308 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 2309 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 2310 -import org.jivesoftware.smackx.jingle.media.PayloadType; 2311 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder; 2312 -import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder; 2313 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 2314 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 2315 - 2316 -import java.util.ArrayList; 2317 -import java.util.List; 2318 - 2319 -/** 2320 - * Implements a JingleMediaManager for ScreenSharing. 2321 - * It currently uses an Audio payload Type. Which needs to be fixed in the next version. 2322 - * 2323 - * @author Thiago Camargo 2324 - */ 2325 - 2326 -public class ScreenShareMediaManager extends JingleMediaManager { 2327 - 2328 - public static final String MEDIA_NAME = "ScreenShare"; 2329 - 2330 - private List<PayloadType> payloads = new ArrayList<PayloadType>(); 2331 - 2332 - private ImageDecoder decoder = null; 2333 - private ImageEncoder encoder = null; 2334 - 2335 - public ScreenShareMediaManager(JingleTransportManager transportManager) { 2336 - super(transportManager); 2337 - setupPayloads(); 2338 - } 2339 - 2340 - /** 2341 - * Setup API supported Payloads 2342 - */ 2343 - private void setupPayloads() { 2344 - payloads.add(new PayloadType.Audio(30, "sshare")); 2345 - } 2346 - 2347 - /** 2348 - * Return all supported Payloads for this Manager. 2349 - * 2350 - * @return The Payload List 2351 - */ 2352 - public List<PayloadType> getPayloads() { 2353 - return payloads; 2354 - } 2355 - 2356 - /** 2357 - * Returns a new JingleMediaSession 2358 - * 2359 - * @param payloadType payloadType 2360 - * @param remote remote Candidate 2361 - * @param local local Candidate 2362 - * @return JingleMediaSession JingleMediaSession 2363 - */ 2364 - public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { 2365 - ScreenShareSession session = null; 2366 - session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession); 2367 - if (encoder != null) { 2368 - session.setEncoder(encoder); 2369 - } 2370 - if (decoder != null) { 2371 - session.setDecoder(decoder); 2372 - } 2373 - return session; 2374 - } 2375 - 2376 - public PayloadType getPreferredPayloadType() { 2377 - return super.getPreferredPayloadType(); 2378 - } 2379 - 2380 - public ImageDecoder getDecoder() { 2381 - return decoder; 2382 - } 2383 - 2384 - public void setDecoder(ImageDecoder decoder) { 2385 - this.decoder = decoder; 2386 - } 2387 - 2388 - public ImageEncoder getEncoder() { 2389 - return encoder; 2390 - } 2391 - 2392 - public void setEncoder(ImageEncoder encoder) { 2393 - this.encoder = encoder; 2394 - } 2395 - 2396 - public String getName() { 2397 - return MEDIA_NAME; 2398 - } 2399 -} 2400 Index: org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java 2401 =================================================================== 2402 --- org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (revision 11644) 2403 +++ org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (working copy) 2404 @@ -1,106 +0,0 @@ 2405 -/** 2406 - * $RCSfile: MultiMediaManager.java,v $ 2407 - * $Revision: 1.3 $ 2408 - * $Date: 25/12/2006 2409 - * <p/> 2410 - * Copyright 2003-2006 Jive Software. 2411 - * <p/> 2412 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 2413 - * you may not use this file except in compliance with the License. 2414 - * You may obtain a copy of the License at 2415 - * <p/> 2416 - * http://www.apache.org/licenses/LICENSE-2.0 2417 - * <p/> 2418 - * Unless required by applicable law or agreed to in writing, software 2419 - * distributed under the License is distributed on an "AS IS" BASIS, 2420 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2421 - * See the License for the specific language governing permissions and 2422 - * limitations under the License. 2423 - */ 2424 - 2425 -package org.jivesoftware.smackx.jingle.mediaimpl.multi; 2426 - 2427 -import org.jivesoftware.smackx.jingle.JingleSession; 2428 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 2429 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 2430 -import org.jivesoftware.smackx.jingle.media.PayloadType; 2431 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 2432 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 2433 - 2434 -import java.util.ArrayList; 2435 -import java.util.List; 2436 - 2437 -/** 2438 - * Implements a MultiMediaManager using other JingleMediaManager implementations. 2439 - * It supports every Codecs that JingleMediaManagers added has. 2440 - * 2441 - * @author Thiago Camargo 2442 - */ 2443 - 2444 -public class MultiMediaManager extends JingleMediaManager { 2445 - 2446 - public static final String MEDIA_NAME = "Multi"; 2447 - 2448 - private List<JingleMediaManager> managers = new ArrayList<JingleMediaManager>(); 2449 - 2450 - private PayloadType preferredPayloadType = null; 2451 - 2452 - public MultiMediaManager(JingleTransportManager transportManager) { 2453 - super(transportManager); 2454 - } 2455 - 2456 - public void addMediaManager(JingleMediaManager manager) { 2457 - managers.add(manager); 2458 - } 2459 - 2460 - public void removeMediaManager(JingleMediaManager manager) { 2461 - managers.remove(manager); 2462 - } 2463 - 2464 - /** 2465 - * Return all supported Payloads for this Manager. 2466 - * 2467 - * @return The Payload List 2468 - */ 2469 - public List<PayloadType> getPayloads() { 2470 - List<PayloadType> list = new ArrayList<PayloadType>(); 2471 - if (preferredPayloadType != null) list.add(preferredPayloadType); 2472 - for (JingleMediaManager manager : managers) { 2473 - for (PayloadType payloadType : manager.getPayloads()) { 2474 - if (!list.contains(payloadType) && !payloadType.equals(preferredPayloadType)) 2475 - list.add(payloadType); 2476 - } 2477 - } 2478 - return list; 2479 - } 2480 - 2481 - /** 2482 - * Returns a new JingleMediaSession 2483 - * 2484 - * @param payloadType payloadType 2485 - * @param remote remote Candidate 2486 - * @param local local Candidate 2487 - * @return JingleMediaSession JingleMediaSession 2488 - */ 2489 - public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { 2490 - for (JingleMediaManager manager : managers) { 2491 - if (manager.getPayloads().contains(payloadType)) { 2492 - return manager.createMediaSession(payloadType, remote, local, jingleSession); 2493 - } 2494 - } 2495 - return null; 2496 - } 2497 - 2498 - public PayloadType getPreferredPayloadType() { 2499 - if (preferredPayloadType != null) return preferredPayloadType; 2500 - return super.getPreferredPayloadType(); 2501 - } 2502 - 2503 - public void setPreferredPayloadType(PayloadType preferredPayloadType) { 2504 - this.preferredPayloadType = preferredPayloadType; 2505 - } 2506 - 2507 - public String getName() { 2508 - return MEDIA_NAME; 2509 - } 2510 -} 2511 Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java 2512 =================================================================== 2513 --- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (revision 11644) 2514 +++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (working copy) 2515 @@ -1,165 +0,0 @@ 2516 -/** 2517 - * $RCSfile: AudioMediaSession.java,v $ 2518 - * $Revision: 1.1 $ 2519 - * $Date: 08/11/2006 2520 - * <p/> 2521 - * Copyright 2003-2006 Jive Software. 2522 - * <p/> 2523 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 2524 - * you may not use this file except in compliance with the License. 2525 - * You may obtain a copy of the License at 2526 - * <p/> 2527 - * http://www.apache.org/licenses/LICENSE-2.0 2528 - * <p/> 2529 - * Unless required by applicable law or agreed to in writing, software 2530 - * distributed under the License is distributed on an "AS IS" BASIS, 2531 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2532 - * See the License for the specific language governing permissions and 2533 - * limitations under the License. 2534 - */ 2535 - 2536 -package org.jivesoftware.smackx.jingle.mediaimpl.jmf; 2537 - 2538 -import java.io.IOException; 2539 -import java.net.ServerSocket; 2540 - 2541 -import javax.media.MediaLocator; 2542 - 2543 -import org.jivesoftware.smackx.jingle.JingleSession; 2544 -import org.jivesoftware.smackx.jingle.SmackLogger; 2545 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 2546 -import org.jivesoftware.smackx.jingle.media.PayloadType; 2547 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 2548 - 2549 -/** 2550 - * This Class implements a complete JingleMediaSession. 2551 - * It sould be used to transmit and receive audio captured from the Mic. 2552 - * This Class should be automaticly controlled by JingleSession. 2553 - * But you could also use in any VOIP application. 2554 - * For better NAT Traversal support this implementation don't support only receive or only transmit. 2555 - * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() 2556 - * 2557 - * @author Thiago Camargo 2558 - */ 2559 -public class AudioMediaSession extends JingleMediaSession { 2560 - 2561 - private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class); 2562 - 2563 - private AudioChannel audioChannel; 2564 - 2565 - /** 2566 - * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates 2567 - * 2568 - * @param payloadType Payload of the jmf 2569 - * @param remote the remote information. The candidate that the jmf will be sent to. 2570 - * @param local the local information. The candidate that will receive the jmf 2571 - * @param locator media locator 2572 - */ 2573 - public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, 2574 - final TransportCandidate local, String locator, JingleSession jingleSession) { 2575 - super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession); 2576 - initialize(); 2577 - } 2578 - 2579 - /** 2580 - * Initialize the Audio Channel to make it able to send and receive audio 2581 - */ 2582 - public void initialize() { 2583 - 2584 - String ip; 2585 - String localIp; 2586 - int localPort; 2587 - int remotePort; 2588 - 2589 - if (this.getLocal().getSymmetric() != null) { 2590 - ip = this.getLocal().getIp(); 2591 - localIp = this.getLocal().getLocalIp(); 2592 - localPort = getFreePort(); 2593 - remotePort = this.getLocal().getSymmetric().getPort(); 2594 - 2595 - LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); 2596 - 2597 - } 2598 - else { 2599 - ip = this.getRemote().getIp(); 2600 - localIp = this.getLocal().getLocalIp(); 2601 - localPort = this.getLocal().getPort(); 2602 - remotePort = this.getRemote().getPort(); 2603 - } 2604 - 2605 - audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this); 2606 - } 2607 - 2608 - /** 2609 - * Starts transmission and for NAT Traversal reasons start receiving also. 2610 - */ 2611 - public void startTrasmit() { 2612 - audioChannel.start(); 2613 - } 2614 - 2615 - /** 2616 - * Set transmit activity. If the active is true, the instance should trasmit. 2617 - * If it is set to false, the instance should pause transmit. 2618 - * 2619 - * @param active active state 2620 - */ 2621 - public void setTrasmit(boolean active) { 2622 - audioChannel.setTrasmit(active); 2623 - } 2624 - 2625 - /** 2626 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 2627 - */ 2628 - public void startReceive() { 2629 - // Do nothing 2630 - } 2631 - 2632 - /** 2633 - * Stops transmission and for NAT Traversal reasons stop receiving also. 2634 - */ 2635 - public void stopTrasmit() { 2636 - if (audioChannel != null) 2637 - audioChannel.stop(); 2638 - } 2639 - 2640 - /** 2641 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 2642 - */ 2643 - public void stopReceive() { 2644 - // Do nothing 2645 - } 2646 - 2647 - /** 2648 - * Obtain a free port we can use. 2649 - * 2650 - * @return A free port number. 2651 - */ 2652 - protected int getFreePort() { 2653 - ServerSocket ss; 2654 - int freePort = 0; 2655 - 2656 - for (int i = 0; i < 10; i++) { 2657 - freePort = (int) (10000 + Math.round(Math.random() * 10000)); 2658 - freePort = freePort % 2 == 0 ? freePort : freePort + 1; 2659 - try { 2660 - ss = new ServerSocket(freePort); 2661 - freePort = ss.getLocalPort(); 2662 - ss.close(); 2663 - return freePort; 2664 - } 2665 - catch (IOException e) { 2666 - e.printStackTrace(); 2667 - } 2668 - } 2669 - try { 2670 - ss = new ServerSocket(0); 2671 - freePort = ss.getLocalPort(); 2672 - ss.close(); 2673 - } 2674 - catch (IOException e) { 2675 - e.printStackTrace(); 2676 - } 2677 - return freePort; 2678 - } 2679 - 2680 -} 2681 Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java 2682 =================================================================== 2683 --- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (revision 11644) 2684 +++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (working copy) 2685 @@ -1,171 +0,0 @@ 2686 -/** 2687 - * $RCSfile: AudioReceiver.java,v $ 2688 - * $Revision: 1.1 $ 2689 - * $Date: 08/11/2006 2690 - * <p/> 2691 - * Copyright 2003-2006 Jive Software. 2692 - * <p/> 2693 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 2694 - * you may not use this file except in compliance with the License. 2695 - * You may obtain a copy of the License at 2696 - * <p/> 2697 - * http://www.apache.org/licenses/LICENSE-2.0 2698 - * <p/> 2699 - * Unless required by applicable law or agreed to in writing, software 2700 - * distributed under the License is distributed on an "AS IS" BASIS, 2701 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2702 - * See the License for the specific language governing permissions and 2703 - * limitations under the License. 2704 - */ 2705 - 2706 -package org.jivesoftware.smackx.jingle.mediaimpl.jmf; 2707 - 2708 -import javax.media.ControllerErrorEvent; 2709 -import javax.media.ControllerEvent; 2710 -import javax.media.ControllerListener; 2711 -import javax.media.Player; 2712 -import javax.media.RealizeCompleteEvent; 2713 -import javax.media.protocol.DataSource; 2714 -import javax.media.rtp.Participant; 2715 -import javax.media.rtp.RTPControl; 2716 -import javax.media.rtp.ReceiveStream; 2717 -import javax.media.rtp.ReceiveStreamListener; 2718 -import javax.media.rtp.SessionListener; 2719 -import javax.media.rtp.event.ByeEvent; 2720 -import javax.media.rtp.event.NewParticipantEvent; 2721 -import javax.media.rtp.event.NewReceiveStreamEvent; 2722 -import javax.media.rtp.event.ReceiveStreamEvent; 2723 -import javax.media.rtp.event.RemotePayloadChangeEvent; 2724 -import javax.media.rtp.event.SessionEvent; 2725 -import javax.media.rtp.event.StreamMappedEvent; 2726 - 2727 -import org.jivesoftware.smackx.jingle.SmackLogger; 2728 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 2729 - 2730 -/** 2731 - * This class implements receive methods and listeners to be used in AudioChannel 2732 - * 2733 - * @author Thiago Camargo 2734 - */ 2735 -public class AudioReceiver implements ReceiveStreamListener, SessionListener, 2736 - ControllerListener { 2737 - 2738 - private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class); 2739 - 2740 - boolean dataReceived = false; 2741 - 2742 - Object dataSync; 2743 - JingleMediaSession jingleMediaSession; 2744 - 2745 - public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) { 2746 - this.dataSync = dataSync; 2747 - this.jingleMediaSession = jingleMediaSession; 2748 - } 2749 - 2750 - /** 2751 - * JingleSessionListener. 2752 - */ 2753 - public synchronized void update(SessionEvent evt) { 2754 - if (evt instanceof NewParticipantEvent) { 2755 - Participant p = ((NewParticipantEvent) evt).getParticipant(); 2756 - LOGGER.error(" - A new participant had just joined: " + p.getCNAME()); 2757 - } 2758 - } 2759 - 2760 - /** 2761 - * ReceiveStreamListener 2762 - */ 2763 - public synchronized void update(ReceiveStreamEvent evt) { 2764 - 2765 - Participant participant = evt.getParticipant(); // could be null. 2766 - ReceiveStream stream = evt.getReceiveStream(); // could be null. 2767 - 2768 - if (evt instanceof RemotePayloadChangeEvent) { 2769 - LOGGER.error(" - Received an RTP PayloadChangeEvent."); 2770 - LOGGER.error("Sorry, cannot handle payload change."); 2771 - 2772 - } 2773 - else if (evt instanceof NewReceiveStreamEvent) { 2774 - 2775 - try { 2776 - stream = evt.getReceiveStream(); 2777 - DataSource ds = stream.getDataSource(); 2778 - 2779 - // Find out the formats. 2780 - RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl"); 2781 - if (ctl != null) { 2782 - LOGGER.error(" - Recevied new RTP stream: " + ctl.getFormat()); 2783 - } 2784 - else 2785 - LOGGER.error(" - Recevied new RTP stream"); 2786 - 2787 - if (participant == null) 2788 - LOGGER.error(" The sender of this stream had yet to be identified."); 2789 - else { 2790 - LOGGER.error(" The stream comes from: " + participant.getCNAME()); 2791 - } 2792 - 2793 - // create a player by passing datasource to the Media Manager 2794 - Player p = javax.media.Manager.createPlayer(ds); 2795 - if (p == null) 2796 - return; 2797 - 2798 - p.addControllerListener(this); 2799 - p.realize(); 2800 - jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : ""); 2801 - 2802 - // Notify intialize() that a new stream had arrived. 2803 - synchronized (dataSync) { 2804 - dataReceived = true; 2805 - dataSync.notifyAll(); 2806 - } 2807 - 2808 - } 2809 - catch (Exception e) { 2810 - LOGGER.error("NewReceiveStreamEvent exception " + e.getMessage()); 2811 - return; 2812 - } 2813 - 2814 - } 2815 - else if (evt instanceof StreamMappedEvent) { 2816 - 2817 - if (stream != null && stream.getDataSource() != null) { 2818 - DataSource ds = stream.getDataSource(); 2819 - // Find out the formats. 2820 - RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl"); 2821 - LOGGER.error(" - The previously unidentified stream "); 2822 - if (ctl != null) 2823 - LOGGER.error(" " + ctl.getFormat()); 2824 - LOGGER.error(" had now been identified as sent by: " + participant.getCNAME()); 2825 - } 2826 - } 2827 - else if (evt instanceof ByeEvent) { 2828 - 2829 - LOGGER.error(" - Got \"bye\" from: " + participant.getCNAME()); 2830 - 2831 - } 2832 - 2833 - } 2834 - 2835 - /** 2836 - * ControllerListener for the Players. 2837 - */ 2838 - public synchronized void controllerUpdate(ControllerEvent ce) { 2839 - 2840 - Player p = (Player) ce.getSourceController(); 2841 - 2842 - if (p == null) 2843 - return; 2844 - 2845 - // Get this when the internal players are realized. 2846 - if (ce instanceof RealizeCompleteEvent) { 2847 - p.start(); 2848 - } 2849 - 2850 - if (ce instanceof ControllerErrorEvent) { 2851 - p.removeControllerListener(this); 2852 - LOGGER.error("Receiver internal error: " + ce); 2853 - } 2854 - 2855 - } 2856 -} 2857 Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java 2858 =================================================================== 2859 --- org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (revision 11644) 2860 +++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (working copy) 2861 @@ -1,170 +0,0 @@ 2862 -/** 2863 - * $RCSfile: JmfMediaManager.java,v $ 2864 - * $Revision: 1.3 $ 2865 - * $Date: 08/11/2006 2866 - * <p/> 2867 - * Copyright 2003-2006 Jive Software. 2868 - * <p/> 2869 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 2870 - * you may not use this file except in compliance with the License. 2871 - * You may obtain a copy of the License at 2872 - * <p/> 2873 - * http://www.apache.org/licenses/LICENSE-2.0 2874 - * <p/> 2875 - * Unless required by applicable law or agreed to in writing, software 2876 - * distributed under the License is distributed on an "AS IS" BASIS, 2877 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2878 - * See the License for the specific language governing permissions and 2879 - * limitations under the License. 2880 - */ 2881 - 2882 -package org.jivesoftware.smackx.jingle.mediaimpl.jmf; 2883 - 2884 -import java.io.File; 2885 -import java.io.IOException; 2886 -import java.util.ArrayList; 2887 -import java.util.List; 2888 - 2889 -import org.jivesoftware.smackx.jingle.JingleSession; 2890 -import org.jivesoftware.smackx.jingle.SmackLogger; 2891 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 2892 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 2893 -import org.jivesoftware.smackx.jingle.media.PayloadType; 2894 -import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; 2895 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 2896 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 2897 - 2898 -/** 2899 - * Implements a jingleMediaManager using JMF based API. 2900 - * It supports GSM and G723 codecs. 2901 - * <i>This API only currently works on windows and Mac.</i> 2902 - * 2903 - * @author Thiago Camargo 2904 - */ 2905 -public class JmfMediaManager extends JingleMediaManager { 2906 - 2907 - private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class); 2908 - 2909 - public static final String MEDIA_NAME = "JMF"; 2910 - 2911 - 2912 - private List<PayloadType> payloads = new ArrayList<PayloadType>(); 2913 - private String mediaLocator = null; 2914 - 2915 - /** 2916 - * Creates a Media Manager instance 2917 - */ 2918 - public JmfMediaManager(JingleTransportManager transportManager) { 2919 - super(transportManager); 2920 - setupPayloads(); 2921 - } 2922 - 2923 - /** 2924 - * Creates a Media Manager instance 2925 - * 2926 - * @param mediaLocator Media Locator 2927 - */ 2928 - public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) { 2929 - super(transportManager); 2930 - this.mediaLocator = mediaLocator; 2931 - setupPayloads(); 2932 - } 2933 - 2934 - /** 2935 - * Returns a new jingleMediaSession 2936 - * 2937 - * @param payloadType payloadType 2938 - * @param remote remote Candidate 2939 - * @param local local Candidate 2940 - * @return JingleMediaSession 2941 - */ 2942 - public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { 2943 - return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession); 2944 - } 2945 - 2946 - /** 2947 - * Setup API supported Payloads 2948 - */ 2949 - private void setupPayloads() { 2950 - payloads.add(new PayloadType.Audio(3, "gsm")); 2951 - payloads.add(new PayloadType.Audio(4, "g723")); 2952 - payloads.add(new PayloadType.Audio(0, "PCMU", 16000)); 2953 - } 2954 - 2955 - /** 2956 - * Return all supported Payloads for this Manager 2957 - * 2958 - * @return The Payload List 2959 - */ 2960 - public List<PayloadType> getPayloads() { 2961 - return payloads; 2962 - } 2963 - 2964 - /** 2965 - * Return the media locator or null if not defined 2966 - * 2967 - * @return media locator 2968 - */ 2969 - public String getMediaLocator() { 2970 - return mediaLocator; 2971 - } 2972 - 2973 - /** 2974 - * Set the media locator 2975 - * 2976 - * @param mediaLocator media locator or null to use default 2977 - */ 2978 - public void setMediaLocator(String mediaLocator) { 2979 - this.mediaLocator = mediaLocator; 2980 - } 2981 - 2982 - /** 2983 - * Runs JMFInit the first time the application is started so that capture 2984 - * devices are properly detected and initialized by JMF. 2985 - */ 2986 - public static void setupJMF() { 2987 - // .jmf is the place where we store the jmf.properties file used 2988 - // by JMF. if the directory does not exist or it does not contain 2989 - // a jmf.properties file. or if the jmf.properties file has 0 length 2990 - // then this is the first time we're running and should continue to 2991 - // with JMFInit 2992 - String homeDir = System.getProperty("user.home"); 2993 - File jmfDir = new File(homeDir, ".jmf"); 2994 - String classpath = System.getProperty("java.class.path"); 2995 - classpath += System.getProperty("path.separator") 2996 - + jmfDir.getAbsolutePath(); 2997 - System.setProperty("java.class.path", classpath); 2998 - 2999 - if (!jmfDir.exists()) 3000 - jmfDir.mkdir(); 3001 - 3002 - File jmfProperties = new File(jmfDir, "jmf.properties"); 3003 - 3004 - if (!jmfProperties.exists()) { 3005 - try { 3006 - jmfProperties.createNewFile(); 3007 - } 3008 - catch (IOException ex) { 3009 - LOGGER.debug("Failed to create jmf.properties"); 3010 - ex.printStackTrace(); 3011 - } 3012 - } 3013 - 3014 - // if we're running on linux checkout that libjmutil.so is where it 3015 - // should be and put it there. 3016 - runLinuxPreInstall(); 3017 - 3018 - //if (jmfProperties.length() == 0) { 3019 - new JMFInit(null, false); 3020 - //} 3021 - 3022 - } 3023 - 3024 - private static void runLinuxPreInstall() { 3025 - // @TODO Implement Linux Pre-Install 3026 - } 3027 - 3028 - public String getName() { 3029 - return MEDIA_NAME; 3030 - } 3031 -} 3032 Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java 3033 =================================================================== 3034 --- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (revision 11644) 3035 +++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (working copy) 3036 @@ -1,553 +0,0 @@ 3037 -/** 3038 - * $RCSfile: AudioChannel.java,v $ 3039 - * $Revision: 1.1 $ 3040 - * $Date: 08/11/2006 3041 - * <p/> 3042 - * Copyright 2003-2006 Jive Software. 3043 - * <p/> 3044 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 3045 - * you may not use this file except in compliance with the License. 3046 - * You may obtain a copy of the License at 3047 - * <p/> 3048 - * http://www.apache.org/licenses/LICENSE-2.0 3049 - * <p/> 3050 - * Unless required by applicable law or agreed to in writing, software 3051 - * distributed under the License is distributed on an "AS IS" BASIS, 3052 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3053 - * See the License for the specific language governing permissions and 3054 - * limitations under the License. 3055 - */ 3056 -package org.jivesoftware.smackx.jingle.mediaimpl.jmf; 3057 - 3058 -import java.io.IOException; 3059 -import java.net.InetAddress; 3060 -import java.net.UnknownHostException; 3061 -import java.util.ArrayList; 3062 -import java.util.List; 3063 - 3064 -import javax.media.Codec; 3065 -import javax.media.Controller; 3066 -import javax.media.ControllerClosedEvent; 3067 -import javax.media.ControllerEvent; 3068 -import javax.media.ControllerListener; 3069 -import javax.media.Format; 3070 -import javax.media.MediaLocator; 3071 -import javax.media.NoProcessorException; 3072 -import javax.media.Processor; 3073 -import javax.media.UnsupportedPlugInException; 3074 -import javax.media.control.BufferControl; 3075 -import javax.media.control.PacketSizeControl; 3076 -import javax.media.control.TrackControl; 3077 -import javax.media.format.AudioFormat; 3078 -import javax.media.protocol.ContentDescriptor; 3079 -import javax.media.protocol.DataSource; 3080 -import javax.media.protocol.PushBufferDataSource; 3081 -import javax.media.protocol.PushBufferStream; 3082 -import javax.media.rtp.InvalidSessionAddressException; 3083 -import javax.media.rtp.RTPManager; 3084 -import javax.media.rtp.SendStream; 3085 -import javax.media.rtp.SessionAddress; 3086 - 3087 -import org.jivesoftware.smackx.jingle.SmackLogger; 3088 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 3089 - 3090 -/** 3091 - * An Easy to use Audio Channel implemented using JMF. 3092 - * It sends and receives jmf for and from desired IPs and ports. 3093 - * Also has a rport Symetric behavior for better NAT Traversal. 3094 - * It send data from a defined port and receive data in the same port, making NAT binds easier. 3095 - * <p/> 3096 - * Send from portA to portB and receive from portB in portA. 3097 - * <p/> 3098 - * Sending 3099 - * portA ---> portB 3100 - * <p/> 3101 - * Receiving 3102 - * portB ---> portA 3103 - * <p/> 3104 - * <i>Transmit and Receive are interdependents. To receive you MUST trasmit. </i> 3105 - * 3106 - * @author Thiago Camargo 3107 - */ 3108 -public class AudioChannel { 3109 - 3110 - private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioChannel.class); 3111 - 3112 - private MediaLocator locator; 3113 - private String localIpAddress; 3114 - private String remoteIpAddress; 3115 - private int localPort; 3116 - private int portBase; 3117 - private Format format; 3118 - 3119 - private Processor processor = null; 3120 - private RTPManager rtpMgrs[]; 3121 - private DataSource dataOutput = null; 3122 - private AudioReceiver audioReceiver; 3123 - 3124 - private List<SendStream> sendStreams = new ArrayList<SendStream>(); 3125 - 3126 - private JingleMediaSession jingleMediaSession; 3127 - 3128 - private boolean started = false; 3129 - 3130 - /** 3131 - * Creates an Audio Channel for a desired jmf locator. For instance: new MediaLocator("dsound://") 3132 - * 3133 - * @param locator media locator 3134 - * @param localIpAddress local IP address 3135 - * @param remoteIpAddress remote IP address 3136 - * @param localPort local port number 3137 - * @param remotePort remote port number 3138 - * @param format audio format 3139 - */ 3140 - public AudioChannel(MediaLocator locator, 3141 - String localIpAddress, 3142 - String remoteIpAddress, 3143 - int localPort, 3144 - int remotePort, 3145 - Format format, JingleMediaSession jingleMediaSession) { 3146 - 3147 - this.locator = locator; 3148 - this.localIpAddress = localIpAddress; 3149 - this.remoteIpAddress = remoteIpAddress; 3150 - this.localPort = localPort; 3151 - this.portBase = remotePort; 3152 - this.format = format; 3153 - this.jingleMediaSession = jingleMediaSession; 3154 - } 3155 - 3156 - /** 3157 - * Starts the transmission. Returns null if transmission started ok. 3158 - * Otherwise it returns a string with the reason why the setup failed. 3159 - * Starts receive also. 3160 - * 3161 - * @return result description 3162 - */ 3163 - public synchronized String start() { 3164 - if (started) return null; 3165 - 3166 - // Create a processor for the specified jmf locator 3167 - String result = createProcessor(); 3168 - if (result != null) { 3169 - started = false; 3170 - } 3171 - 3172 - // Create an RTP session to transmit the output of the 3173 - // processor to the specified IP address and port no. 3174 - result = createTransmitter(); 3175 - if (result != null) { 3176 - processor.close(); 3177 - processor = null; 3178 - started = false; 3179 - } 3180 - else { 3181 - started = true; 3182 - } 3183 - 3184 - // Start the transmission 3185 - processor.start(); 3186 - 3187 - return null; 3188 - } 3189 - 3190 - /** 3191 - * Stops the transmission if already started. 3192 - * Stops the receiver also. 3193 - */ 3194 - public void stop() { 3195 - if (!started) return; 3196 - synchronized (this) { 3197 - try { 3198 - started = false; 3199 - if (processor != null) { 3200 - processor.stop(); 3201 - processor = null; 3202 - 3203 - for (RTPManager rtpMgr : rtpMgrs) { 3204 - rtpMgr.removeReceiveStreamListener(audioReceiver); 3205 - rtpMgr.removeSessionListener(audioReceiver); 3206 - rtpMgr.removeTargets("Session ended."); 3207 - rtpMgr.dispose(); 3208 - } 3209 - 3210 - sendStreams.clear(); 3211 - 3212 - } 3213 - } 3214 - catch (Exception e) { 3215 - e.printStackTrace(); 3216 - } 3217 - } 3218 - } 3219 - 3220 - private String createProcessor() { 3221 - if (locator == null) 3222 - return "Locator is null"; 3223 - 3224 - DataSource ds; 3225 - 3226 - try { 3227 - ds = javax.media.Manager.createDataSource(locator); 3228 - } 3229 - catch (Exception e) { 3230 - // Try JavaSound Locator as a last resort 3231 - try { 3232 - ds = javax.media.Manager.createDataSource(new MediaLocator("javasound://")); 3233 - } 3234 - catch (Exception ee) { 3235 - return "Couldn't create DataSource"; 3236 - } 3237 - } 3238 - 3239 - // Try to create a processor to handle the input jmf locator 3240 - try { 3241 - processor = javax.media.Manager.createProcessor(ds); 3242 - } 3243 - catch (NoProcessorException npe) { 3244 - npe.printStackTrace(); 3245 - return "Couldn't create processor"; 3246 - } 3247 - catch (IOException ioe) { 3248 - ioe.printStackTrace(); 3249 - return "IOException creating processor"; 3250 - } 3251 - 3252 - // Wait for it to configure 3253 - boolean result = waitForState(processor, Processor.Configured); 3254 - if (!result){ 3255 - return "Couldn't configure processor"; 3256 - } 3257 - 3258 - // Get the tracks from the processor 3259 - TrackControl[] tracks = processor.getTrackControls(); 3260 - 3261 - // Do we have atleast one track? 3262 - if (tracks == null || tracks.length < 1){ 3263 - return "Couldn't find tracks in processor"; 3264 - } 3265 - 3266 - // Set the output content descriptor to RAW_RTP 3267 - // This will limit the supported formats reported from 3268 - // Track.getSupportedFormats to only valid RTP formats. 3269 - ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP); 3270 - processor.setContentDescriptor(cd); 3271 - 3272 - Format supported[]; 3273 - Format chosen = null; 3274 - boolean atLeastOneTrack = false; 3275 - 3276 - // Program the tracks. 3277 - for (int i = 0; i < tracks.length; i++) { 3278 - if (tracks[i].isEnabled()) { 3279 - 3280 - supported = tracks[i].getSupportedFormats(); 3281 - 3282 - if (supported.length > 0) { 3283 - for (Format format : supported) { 3284 - if (format instanceof AudioFormat) { 3285 - if (this.format.matches(format)) 3286 - chosen = format; 3287 - } 3288 - } 3289 - if (chosen != null) { 3290 - tracks[i].setFormat(chosen); 3291 - LOGGER.error("Track " + i + " is set to transmit as:"); 3292 - LOGGER.error(" " + chosen); 3293 - 3294 - if (tracks[i].getFormat() instanceof AudioFormat) { 3295 - int packetRate = 20; 3296 - PacketSizeControl pktCtrl = (PacketSizeControl) processor.getControl(PacketSizeControl.class.getName()); 3297 - if (pktCtrl != null) { 3298 - try { 3299 - pktCtrl.setPacketSize(getPacketSize(tracks[i].getFormat(), packetRate)); 3300 - } 3301 - catch (IllegalArgumentException e) { 3302 - pktCtrl.setPacketSize(80); 3303 - // Do nothing 3304 - } 3305 - } 3306 - 3307 - if (tracks[i].getFormat().getEncoding().equals(AudioFormat.ULAW_RTP)) { 3308 - Codec codec[] = new Codec[3]; 3309 - 3310 - codec[0] = new com.ibm.media.codec.audio.rc.RCModule(); 3311 - codec[1] = new com.ibm.media.codec.audio.ulaw.JavaEncoder(); 3312 - codec[2] = new com.sun.media.codec.audio.ulaw.Packetizer(); 3313 - ((com.sun.media.codec.audio.ulaw.Packetizer) codec 3314 - [2]).setPacketSize(160); 3315 - 3316 - try { 3317 - tracks[i].setCodecChain(codec); 3318 - } 3319 - catch (UnsupportedPlugInException e) { 3320 - e.printStackTrace(); 3321 - } 3322 - } 3323 - 3324 - } 3325 - 3326 - atLeastOneTrack = true; 3327 - } 3328 - else 3329 - tracks[i].setEnabled(false); 3330 - } 3331 - else 3332 - tracks[i].setEnabled(false); 3333 - } 3334 - } 3335 - 3336 - if (!atLeastOneTrack) 3337 - return "Couldn't set any of the tracks to a valid RTP format"; 3338 - 3339 - result = waitForState(processor, Controller.Realized); 3340 - if (!result) 3341 - return "Couldn't realize processor"; 3342 - 3343 - // Get the output data source of the processor 3344 - dataOutput = processor.getDataOutput(); 3345 - 3346 - return null; 3347 - } 3348 - 3349 - /** 3350 - * Get the best packet size for a given codec and a codec rate 3351 - * 3352 - * @param codecFormat 3353 - * @param milliseconds 3354 - * @return 3355 - * @throws IllegalArgumentException 3356 - */ 3357 - private int getPacketSize(Format codecFormat, int milliseconds) throws IllegalArgumentException { 3358 - String encoding = codecFormat.getEncoding(); 3359 - if (encoding.equalsIgnoreCase(AudioFormat.GSM) || 3360 - encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) { 3361 - return milliseconds * 4; // 1 byte per millisec 3362 - } 3363 - else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) || 3364 - encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) { 3365 - return milliseconds * 8; 3366 - } 3367 - else { 3368 - throw new IllegalArgumentException("Unknown codec type"); 3369 - } 3370 - } 3371 - 3372 - /** 3373 - * Use the RTPManager API to create sessions for each jmf 3374 - * track of the processor. 3375 - * 3376 - * @return description 3377 - */ 3378 - private String createTransmitter() { 3379 - 3380 - // Cheated. Should have checked the type. 3381 - PushBufferDataSource pbds = (PushBufferDataSource) dataOutput; 3382 - PushBufferStream pbss[] = pbds.getStreams(); 3383 - 3384 - rtpMgrs = new RTPManager[pbss.length]; 3385 - SessionAddress localAddr, destAddr; 3386 - InetAddress ipAddr; 3387 - SendStream sendStream; 3388 - audioReceiver = new AudioReceiver(this, jingleMediaSession); 3389 - int port; 3390 - 3391 - for (int i = 0; i < pbss.length; i++) { 3392 - try { 3393 - rtpMgrs[i] = RTPManager.newInstance(); 3394 - 3395 - port = portBase + 2 * i; 3396 - ipAddr = InetAddress.getByName(remoteIpAddress); 3397 - 3398 - localAddr = new SessionAddress(InetAddress.getByName(this.localIpAddress), 3399 - localPort); 3400 - 3401 - destAddr = new SessionAddress(ipAddr, port); 3402 - 3403 - rtpMgrs[i].addReceiveStreamListener(audioReceiver); 3404 - rtpMgrs[i].addSessionListener(audioReceiver); 3405 - 3406 - BufferControl bc = (BufferControl) rtpMgrs[i].getControl("javax.media.control.BufferControl"); 3407 - if (bc != null) { 3408 - int bl = 160; 3409 - bc.setBufferLength(bl); 3410 - } 3411 - 3412 - try { 3413 - 3414 - rtpMgrs[i].initialize(localAddr); 3415 - 3416 - } 3417 - catch (InvalidSessionAddressException e) { 3418 - // In case the local address is not allowed to read, we user another local address 3419 - SessionAddress sessAddr = new SessionAddress(); 3420 - localAddr = new SessionAddress(sessAddr.getDataAddress(), 3421 - localPort); 3422 - rtpMgrs[i].initialize(localAddr); 3423 - } 3424 - 3425 - rtpMgrs[i].addTarget(destAddr); 3426 - 3427 - LOGGER.error("Created RTP session at " + localPort + " to: " + remoteIpAddress + " " + port); 3428 - 3429 - sendStream = rtpMgrs[i].createSendStream(dataOutput, i); 3430 - 3431 - sendStreams.add(sendStream); 3432 - 3433 - sendStream.start(); 3434 - 3435 - } 3436 - catch (Exception e) { 3437 - e.printStackTrace(); 3438 - return e.getMessage(); 3439 - } 3440 - } 3441 - 3442 - return null; 3443 - } 3444 - 3445 - /** 3446 - * Set transmit activity. If the active is true, the instance should trasmit. 3447 - * If it is set to false, the instance should pause transmit. 3448 - * 3449 - * @param active active state 3450 - */ 3451 - public void setTrasmit(boolean active) { 3452 - for (SendStream sendStream : sendStreams) { 3453 - try { 3454 - if (active) { 3455 - sendStream.start(); 3456 - LOGGER.debug("START"); 3457 - } 3458 - else { 3459 - sendStream.stop(); 3460 - LOGGER.debug("STOP"); 3461 - } 3462 - } 3463 - catch (IOException e) { 3464 - e.printStackTrace(); 3465 - } 3466 - 3467 - } 3468 - } 3469 - 3470 - /** 3471 - * ************************************************************* 3472 - * Convenience methods to handle processor's state changes. 3473 - * ************************************************************** 3474 - */ 3475 - 3476 - private Integer stateLock = 0; 3477 - private boolean failed = false; 3478 - 3479 - Integer getStateLock() { 3480 - return stateLock; 3481 - } 3482 - 3483 - void setFailed() { 3484 - failed = true; 3485 - } 3486 - 3487 - private synchronized boolean waitForState(Processor p, int state) { 3488 - p.addControllerListener(new StateListener()); 3489 - failed = false; 3490 - 3491 - // Call the required method on the processor 3492 - if (state == Processor.Configured) { 3493 - p.configure(); 3494 - } 3495 - else if (state == Processor.Realized) { 3496 - p.realize(); 3497 - } 3498 - 3499 - // Wait until we get an event that confirms the 3500 - // success of the method, or a failure event. 3501 - // See StateListener inner class 3502 - while (p.getState() < state && !failed) { 3503 - synchronized (getStateLock()) { 3504 - try { 3505 - getStateLock().wait(); 3506 - } 3507 - catch (InterruptedException ie) { 3508 - return false; 3509 - } 3510 - } 3511 - } 3512 - 3513 - return !failed; 3514 - } 3515 - 3516 - /** 3517 - * ************************************************************* 3518 - * Inner Classes 3519 - * ************************************************************** 3520 - */ 3521 - 3522 - class StateListener implements ControllerListener { 3523 - 3524 - public void controllerUpdate(ControllerEvent ce) { 3525 - 3526 - // If there was an error during configure or 3527 - // realize, the processor will be closed 3528 - if (ce instanceof ControllerClosedEvent) 3529 - setFailed(); 3530 - 3531 - // All controller events, send a notification 3532 - // to the waiting thread in waitForState method. 3533 - if (ce != null) { 3534 - synchronized (getStateLock()) { 3535 - getStateLock().notifyAll(); 3536 - } 3537 - } 3538 - } 3539 - } 3540 - 3541 - public static void main(String args[]) { 3542 - 3543 - InetAddress localhost; 3544 - try { 3545 - localhost = InetAddress.getLocalHost(); 3546 - 3547 - AudioChannel audioChannel0 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7002, 7020, new AudioFormat(AudioFormat.GSM_RTP), null); 3548 - AudioChannel audioChannel1 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7020, 7002, new AudioFormat(AudioFormat.GSM_RTP), null); 3549 - 3550 - audioChannel0.start(); 3551 - audioChannel1.start(); 3552 - 3553 - try { 3554 - Thread.sleep(5000); 3555 - } 3556 - catch (InterruptedException e) { 3557 - e.printStackTrace(); 3558 - } 3559 - 3560 - audioChannel0.setTrasmit(false); 3561 - audioChannel1.setTrasmit(false); 3562 - 3563 - try { 3564 - Thread.sleep(5000); 3565 - } 3566 - catch (InterruptedException e) { 3567 - e.printStackTrace(); 3568 - } 3569 - 3570 - audioChannel0.setTrasmit(true); 3571 - audioChannel1.setTrasmit(true); 3572 - 3573 - try { 3574 - Thread.sleep(5000); 3575 - } 3576 - catch (InterruptedException e) { 3577 - e.printStackTrace(); 3578 - } 3579 - 3580 - audioChannel0.stop(); 3581 - audioChannel1.stop(); 3582 - 3583 - } 3584 - catch (UnknownHostException e) { 3585 - e.printStackTrace(); 3586 - } 3587 - 3588 - } 3589 -} 3590 \ No newline at end of file 3591 Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java 3592 =================================================================== 3593 --- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (revision 11644) 3594 +++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (working copy) 3595 @@ -1,55 +0,0 @@ 3596 -/** 3597 - * $RCSfile: AudioFormatUtils.java,v $ 3598 - * $Revision: 1.1 $ 3599 - * $Date: 08/11/2006 3600 - * <p/> 3601 - * Copyright 2003-2006 Jive Software. 3602 - * <p/> 3603 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 3604 - * you may not use this file except in compliance with the License. 3605 - * You may obtain a copy of the License at 3606 - * <p/> 3607 - * http://www.apache.org/licenses/LICENSE-2.0 3608 - * <p/> 3609 - * Unless required by applicable law or agreed to in writing, software 3610 - * distributed under the License is distributed on an "AS IS" BASIS, 3611 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3612 - * See the License for the specific language governing permissions and 3613 - * limitations under the License. 3614 - */ 3615 -package org.jivesoftware.smackx.jingle.mediaimpl.jmf; 3616 - 3617 -import org.jivesoftware.smackx.jingle.media.PayloadType; 3618 - 3619 -import javax.media.format.AudioFormat; 3620 - 3621 -/** 3622 - * Audio Format Utils. 3623 - * 3624 - * @author Thiago Camargo 3625 - */ 3626 -public class AudioFormatUtils { 3627 - 3628 - /** 3629 - * Return a JMF AudioFormat for a given Jingle Payload type. 3630 - * Return null if the payload is not supported by this jmf API. 3631 - * 3632 - * @param payloadtype payloadtype 3633 - * @return correspondent audioType 3634 - */ 3635 - public static AudioFormat getAudioFormat(PayloadType payloadtype) { 3636 - 3637 - switch (payloadtype.getId()) { 3638 - case 0: 3639 - return new AudioFormat(AudioFormat.ULAW_RTP); 3640 - case 3: 3641 - return new AudioFormat(AudioFormat.GSM_RTP); 3642 - case 4: 3643 - return new AudioFormat(AudioFormat.G723_RTP); 3644 - default: 3645 - return null; 3646 - } 3647 - 3648 - } 3649 - 3650 -} 3651 Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java 3652 =================================================================== 3653 --- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (revision 11644) 3654 +++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (working copy) 3655 @@ -1,134 +0,0 @@ 3656 -/** 3657 - * $RCSfile: SpeexMediaManager.java,v $ 3658 - * $Revision: 1.3 $ 3659 - * $Date: 25/12/2006 3660 - * <p/> 3661 - * Copyright 2003-2006 Jive Software. 3662 - * <p/> 3663 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 3664 - * you may not use this file except in compliance with the License. 3665 - * You may obtain a copy of the License at 3666 - * <p/> 3667 - * http://www.apache.org/licenses/LICENSE-2.0 3668 - * <p/> 3669 - * Unless required by applicable law or agreed to in writing, software 3670 - * distributed under the License is distributed on an "AS IS" BASIS, 3671 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3672 - * See the License for the specific language governing permissions and 3673 - * limitations under the License. 3674 - */ 3675 -package org.jivesoftware.smackx.jingle.mediaimpl.jspeex; 3676 - 3677 -import java.io.File; 3678 -import java.io.IOException; 3679 -import java.util.ArrayList; 3680 -import java.util.List; 3681 - 3682 -import org.jivesoftware.smackx.jingle.JingleSession; 3683 -import org.jivesoftware.smackx.jingle.SmackLogger; 3684 -import org.jivesoftware.smackx.jingle.media.JingleMediaManager; 3685 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 3686 -import org.jivesoftware.smackx.jingle.media.PayloadType; 3687 -import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; 3688 -import org.jivesoftware.smackx.jingle.nat.JingleTransportManager; 3689 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 3690 - 3691 -/** 3692 - * Implements a jingleMediaManager using JMF based API and JSpeex. 3693 - * It supports Speex codec. 3694 - * <i>This API only currently works on windows.</i> 3695 - * 3696 - * @author Thiago Camargo 3697 - */ 3698 -public class SpeexMediaManager extends JingleMediaManager { 3699 - 3700 - private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class); 3701 - 3702 - public static final String MEDIA_NAME = "Speex"; 3703 - 3704 - private List<PayloadType> payloads = new ArrayList<PayloadType>(); 3705 - 3706 - public SpeexMediaManager(JingleTransportManager transportManager) { 3707 - super(transportManager); 3708 - setupPayloads(); 3709 - setupJMF(); 3710 - } 3711 - 3712 - /** 3713 - * Returns a new jingleMediaSession 3714 - * 3715 - * @param payloadType payloadType 3716 - * @param remote remote Candidate 3717 - * @param local local Candidate 3718 - * @return JingleMediaSession 3719 - */ 3720 - public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) { 3721 - return new AudioMediaSession(payloadType, remote, local, null,null); 3722 - } 3723 - 3724 - /** 3725 - * Setup API supported Payloads 3726 - */ 3727 - private void setupPayloads() { 3728 - payloads.add(new PayloadType.Audio(15, "speex")); 3729 - } 3730 - 3731 - /** 3732 - * Return all supported Payloads for this Manager 3733 - * 3734 - * @return The Payload List 3735 - */ 3736 - public List<PayloadType> getPayloads() { 3737 - return payloads; 3738 - } 3739 - 3740 - /** 3741 - * Runs JMFInit the first time the application is started so that capture 3742 - * devices are properly detected and initialized by JMF. 3743 - */ 3744 - public static void setupJMF() { 3745 - // .jmf is the place where we store the jmf.properties file used 3746 - // by JMF. if the directory does not exist or it does not contain 3747 - // a jmf.properties file. or if the jmf.properties file has 0 length 3748 - // then this is the first time we're running and should continue to 3749 - // with JMFInit 3750 - String homeDir = System.getProperty("user.home"); 3751 - File jmfDir = new File(homeDir, ".jmf"); 3752 - String classpath = System.getProperty("java.class.path"); 3753 - classpath += System.getProperty("path.separator") 3754 - + jmfDir.getAbsolutePath(); 3755 - System.setProperty("java.class.path", classpath); 3756 - 3757 - if (!jmfDir.exists()) 3758 - jmfDir.mkdir(); 3759 - 3760 - File jmfProperties = new File(jmfDir, "jmf.properties"); 3761 - 3762 - if (!jmfProperties.exists()) { 3763 - try { 3764 - jmfProperties.createNewFile(); 3765 - } 3766 - catch (IOException ex) { 3767 - LOGGER.debug("Failed to create jmf.properties"); 3768 - ex.printStackTrace(); 3769 - } 3770 - } 3771 - 3772 - // if we're running on linux checkout that libjmutil.so is where it 3773 - // should be and put it there. 3774 - runLinuxPreInstall(); 3775 - 3776 - if (jmfProperties.length() == 0) { 3777 - new JMFInit(null, false); 3778 - } 3779 - 3780 - } 3781 - 3782 - private static void runLinuxPreInstall() { 3783 - // @TODO Implement Linux Pre-Install 3784 - } 3785 - 3786 - public String getName() { 3787 - return MEDIA_NAME; 3788 - } 3789 -} 3790 Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java 3791 =================================================================== 3792 --- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (revision 11644) 3793 +++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (working copy) 3794 @@ -1,245 +0,0 @@ 3795 -/** 3796 - * $RCSfile: AudioMediaSession.java,v $ 3797 - * $Revision: 1.1 $ 3798 - * $Date: 25/12/2006 3799 - * <p/> 3800 - * Copyright 2003-2006 Jive Software. 3801 - * <p/> 3802 - * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 3803 - * you may not use this file except in compliance with the License. 3804 - * You may obtain a copy of the License at 3805 - * <p/> 3806 - * http://www.apache.org/licenses/LICENSE-2.0 3807 - * <p/> 3808 - * Unless required by applicable law or agreed to in writing, software 3809 - * distributed under the License is distributed on an "AS IS" BASIS, 3810 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3811 - * See the License for the specific language governing permissions and 3812 - * limitations under the License. 3813 - */ 3814 - 3815 -package org.jivesoftware.smackx.jingle.mediaimpl.jspeex; 3816 - 3817 -import java.io.IOException; 3818 -import java.net.DatagramSocket; 3819 -import java.net.InetAddress; 3820 -import java.net.ServerSocket; 3821 -import java.security.GeneralSecurityException; 3822 - 3823 -import javax.media.NoProcessorException; 3824 -import javax.media.format.UnsupportedFormatException; 3825 -import javax.media.rtp.rtcp.SenderReport; 3826 -import javax.media.rtp.rtcp.SourceDescription; 3827 - 3828 -import mil.jfcom.cie.media.session.MediaSession; 3829 -import mil.jfcom.cie.media.session.MediaSessionListener; 3830 -import mil.jfcom.cie.media.session.StreamPlayer; 3831 -import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat; 3832 - 3833 -import org.jivesoftware.smackx.jingle.JingleSession; 3834 -import org.jivesoftware.smackx.jingle.SmackLogger; 3835 -import org.jivesoftware.smackx.jingle.media.JingleMediaSession; 3836 -import org.jivesoftware.smackx.jingle.media.PayloadType; 3837 -import org.jivesoftware.smackx.jingle.nat.TransportCandidate; 3838 - 3839 -/** 3840 - * This Class implements a complete JingleMediaSession. 3841 - * It sould be used to transmit and receive audio captured from the Mic. 3842 - * This Class should be automaticly controlled by JingleSession. 3843 - * But you could also use in any VOIP application. 3844 - * For better NAT Traversal support this implementation don't support only receive or only transmit. 3845 - * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit() 3846 - * 3847 - * @author Thiago Camargo 3848 - */ 3849 - 3850 -public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener { 3851 - 3852 - private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class); 3853 - 3854 - private MediaSession mediaSession; 3855 - 3856 - /** 3857 - * Create a Session using Speex Codec 3858 - * 3859 - * @param localhost localHost 3860 - * @param localPort localPort 3861 - * @param remoteHost remoteHost 3862 - * @param remotePort remotePort 3863 - * @param eventHandler eventHandler 3864 - * @param quality quality 3865 - * @param secure secure 3866 - * @param micOn micOn 3867 - * @return MediaSession 3868 - * @throws NoProcessorException 3869 - * @throws UnsupportedFormatException 3870 - * @throws IOException 3871 - * @throws GeneralSecurityException 3872 - */ 3873 - 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 { 3874 - 3875 - SpeexFormat.setFramesPerPacket(1); 3876 - /** 3877 - * The master key. Hardcoded for now. 3878 - */ 3879 - 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}; 3880 - 3881 - /** 3882 - * The master salt. Hardcoded for now. 3883 - */ 3884 - 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}; 3885 - 3886 - DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort); 3887 - MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt); 3888 - session.setListener(eventHandler); 3889 - 3890 - session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester (a] 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)}); 3891 - return session; 3892 - } 3893 - 3894 - 3895 - /** 3896 - * Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates 3897 - * 3898 - * @param payloadType Payload of the jmf 3899 - * @param remote the remote information. The candidate that the jmf will be sent to. 3900 - * @param local the local information. The candidate that will receive the jmf 3901 - * @param locator media locator 3902 - */ 3903 - public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, 3904 - final TransportCandidate local, String locator, JingleSession jingleSession) { 3905 - super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession); 3906 - initialize(); 3907 - } 3908 - 3909 - /** 3910 - * Initialize the Audio Channel to make it able to send and receive audio 3911 - */ 3912 - public void initialize() { 3913 - 3914 - String ip; 3915 - String localIp; 3916 - int localPort; 3917 - int remotePort; 3918 - 3919 - if (this.getLocal().getSymmetric() != null) { 3920 - ip = this.getLocal().getIp(); 3921 - localIp = this.getLocal().getLocalIp(); 3922 - localPort = getFreePort(); 3923 - remotePort = this.getLocal().getSymmetric().getPort(); 3924 - 3925 - LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); 3926 - 3927 - } 3928 - else { 3929 - ip = this.getRemote().getIp(); 3930 - localIp = this.getLocal().getLocalIp(); 3931 - localPort = this.getLocal().getPort(); 3932 - remotePort = this.getRemote().getPort(); 3933 - } 3934 - 3935 - try { 3936 - mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true); 3937 - } 3938 - catch (NoProcessorException e) { 3939 - e.printStackTrace(); 3940 - } 3941 - catch (UnsupportedFormatException e) { 3942 - e.printStackTrace(); 3943 - } 3944 - catch (IOException e) { 3945 - e.printStackTrace(); 3946 - } 3947 - catch (GeneralSecurityException e) { 3948 - e.printStackTrace(); 3949 - } 3950 - } 3951 - 3952 - /** 3953 - * Starts transmission and for NAT Traversal reasons start receiving also. 3954 - */ 3955 - public void startTrasmit() { 3956 - try { 3957 - LOGGER.debug("start"); 3958 - mediaSession.start(true); 3959 - this.mediaReceived(""); 3960 - } 3961 - catch (IOException e) { 3962 - e.printStackTrace(); 3963 - } 3964 - } 3965 - 3966 - /** 3967 - * Set transmit activity. If the active is true, the instance should trasmit. 3968 - * If it is set to false, the instance should pause transmit. 3969 - * 3970 - * @param active active state 3971 - */ 3972 - public void setTrasmit(boolean active) { 3973 - // Do nothing 3974 - } 3975 - 3976 - /** 3977 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 3978 - */ 3979 - public void startReceive() { 3980 - // Do nothing 3981 - } 3982 - 3983 - /** 3984 - * Stops transmission and for NAT Traversal reasons stop receiving also. 3985 - */ 3986 - public void stopTrasmit() { 3987 - if (mediaSession != null) 3988 - mediaSession.close(); 3989 - } 3990 - 3991 - /** 3992 - * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf 3993 - */ 3994 - public void stopReceive() { 3995 - // Do nothing 3996 - } 3997 - 3998 - public void newStreamIdentified(StreamPlayer streamPlayer) { 3999 - } 4000 - 4001 - public void senderReportReceived(SenderReport report) { 4002 - } 4003 - 4004 - public void streamClosed(StreamPlayer stream, boolean timeout) { 4005 - } 4006 - 4007 - /** 4008 - * Obtain a free port we can use. 4009 - * 4010 - * @return A free port number. 4011 - */ 4012 - protected int getFreePort() { 4013 - ServerSocket ss; 4014 - int freePort = 0; 4015 - 4016 - for (int i = 0; i < 10; i++) { 4017 - freePort = (int) (10000 + Math.round(Math.random() * 10000)); 4018 - freePort = freePort % 2 == 0 ? freePort : freePort + 1; 4019 - try { 4020 - ss = new ServerSocket(freePort); 4021 - freePort = ss.getLocalPort(); 4022 - ss.close(); 4023 - return freePort; 4024 - } 4025 - catch (IOException e) { 4026 - e.printStackTrace(); 4027 - } 4028 - } 4029 - try { 4030 - ss = new ServerSocket(0); 4031 - freePort = ss.getLocalPort(); 4032 - ss.close(); 4033 - } 4034 - catch (IOException e) { 4035 - e.printStackTrace(); 4036 - } 4037 - return freePort; 4038 - } 4039 -} 4040