| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License") + you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.openmeetings.screen.webstart; |
| |
| import java.awt.MouseInfo; |
| import java.awt.Point; |
| import java.awt.PointerInfo; |
| import java.awt.Rectangle; |
| import java.awt.Robot; |
| import java.awt.Toolkit; |
| import java.awt.datatransfer.Clipboard; |
| import java.awt.datatransfer.DataFlavor; |
| import java.awt.datatransfer.StringSelection; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| import java.awt.event.InputEvent; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.WindowAdapter; |
| import java.awt.event.WindowEvent; |
| import java.awt.image.BufferedImage; |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.apache.mina.core.buffer.IoBuffer; |
| import org.openmeetings.screen.webstart.gui.ScreenDimensions; |
| import org.openmeetings.screen.webstart.gui.ScreenDimensions.ScreenQuality; |
| import org.openmeetings.screen.webstart.gui.ScreenSharerFrame; |
| import org.red5.io.ITagReader; |
| import org.red5.io.ITagWriter; |
| import org.red5.io.utils.ObjectMap; |
| import org.red5.server.api.event.IEvent; |
| import org.red5.server.api.service.IPendingServiceCall; |
| import org.red5.server.net.rtmp.Channel; |
| import org.red5.server.net.rtmp.RTMPConnection; |
| import org.red5.server.net.rtmp.codec.RTMP; |
| import org.red5.server.net.rtmp.event.Notify; |
| import org.red5.server.net.rtmp.event.VideoData; |
| import org.red5.server.net.rtmp.message.Header; |
| import org.red5.server.net.rtmp.status.StatusCodes; |
| import org.red5.server.stream.message.RTMPMessage; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class CoreScreenShare { |
| |
| private static final Logger logger = LoggerFactory |
| .getLogger(CoreScreenShare.class); |
| |
| private IScreenShare instance = null; |
| |
| public boolean startPublish = false; |
| public Integer playStreamId; |
| public Integer publishStreamId; |
| public String publishName; |
| public ITagWriter writer; |
| public ITagReader reader; |
| public IoBuffer buffer; |
| public CaptureScreen capture = null; |
| public Thread thread = null; |
| |
| public ScreenSharerFrame frame; |
| |
| public String host = "btg199251"; |
| public String app = "oflaDemo"; |
| public int port = 1935; |
| public int defaultQuality = 1; |
| |
| public Long organization_id = 0L; |
| public Long user_id = null; |
| public Boolean allowRecording = true; |
| |
| private boolean startStreaming = false; |
| private boolean startRecording = false; |
| private boolean startPublishing = false; |
| public float Ampl_factor = 1f; |
| public boolean isConnected = false; |
| |
| public Map<Integer, Boolean> currentPressedKeys = new HashMap<Integer, Boolean>(); |
| |
| // ------------------------------------------------------------------------ |
| // |
| // Main |
| // |
| // ------------------------------------------------------------------------ |
| |
| public CoreScreenShare(IScreenShare instance) { |
| this.instance = instance; |
| } |
| |
| public void main(String[] args) { |
| try { |
| for (String arg : args) { |
| logger.debug("arg: " + arg); |
| } |
| String[] textArray = null; |
| if (args.length > 8) { |
| host = args[0]; |
| app = args[1]; |
| port = Integer.parseInt(args[2]); |
| publishName = args[3]; |
| |
| String labelTexts = args[4]; |
| |
| organization_id = Long.parseLong(args[5]); |
| |
| defaultQuality = Integer.parseInt(args[6]); |
| user_id = Long.parseLong(args[7]); |
| allowRecording = Boolean.parseBoolean(args[8]); |
| |
| if (labelTexts.length() > 0) { |
| textArray = labelTexts.split(";"); |
| |
| logger.debug("labelTexts :: " + labelTexts); |
| |
| logger.debug("textArray Length " + textArray.length); |
| |
| for (int i = 0; i < textArray.length; i++) { |
| logger.debug(i + " :: " + textArray[i]); |
| } |
| } |
| } else { |
| System.exit(0); |
| } |
| |
| logger.debug("host: " + host + ", app: " |
| + app + ", port: " + port + ", publish: " |
| + publishName); |
| |
| createWindow(textArray); |
| } catch (Exception err) { |
| logger.error("", err); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // |
| // GUI |
| // |
| // ------------------------------------------------------------------------ |
| public void createWindow(String[] textArray) { |
| try { |
| frame = new ScreenSharerFrame(this, textArray); |
| frame.addWindowListener(new WindowAdapter() { |
| public void windowClosing(WindowEvent e) { |
| frame.setVisible(false); |
| System.exit(0); |
| } |
| }); |
| frame.setVisible(true); |
| frame.setRecordingTabEnabled(allowRecording); |
| |
| logger.debug("initialized"); |
| |
| } catch (Exception err) { |
| logger.error("createWindow Exception: ", err); |
| err.printStackTrace(); |
| } |
| } |
| |
| synchronized public void sendCursorStatus() { |
| try { |
| PointerInfo a = MouseInfo.getPointerInfo(); |
| Point mouseP = a.getLocation(); |
| |
| float scaleFactor = (1.0f * ScreenDimensions.resizeX) / ScreenDimensions.spinnerWidth; |
| |
| // Real size: Real mouse position = Resize : X |
| int x = (int)(Ampl_factor * (mouseP.getX() - ScreenDimensions.spinnerX) * scaleFactor); |
| int y = (int)(Ampl_factor * (mouseP.getY() - ScreenDimensions.spinnerY) * scaleFactor); |
| |
| HashMap<String, Object> cursorPosition = new HashMap<String, Object>(); |
| cursorPosition.put("publicSID", this.publishName); |
| cursorPosition.put("cursor_x", x); |
| cursorPosition.put("cursor_y", y); |
| |
| if (instance.getConnection() != null) { |
| instance.invoke("setNewCursorPosition", new Object[] { cursorPosition }, instance); |
| } |
| } catch (NullPointerException npe) { |
| //noop |
| } catch (Exception err) { |
| System.out.println("captureScreenStart Exception: "); |
| System.err.println(err); |
| frame.setStatus("Exception: " + err); |
| logger.error("[sendCursorStatus]", err); |
| } |
| } |
| |
| synchronized public void setConnectionAsSharingClient() { |
| try { |
| logger.debug("########## setConnectionAsSharingClient"); |
| |
| HashMap<Object, Object> map = new HashMap<Object, Object>(); |
| map.put("screenX", ScreenDimensions.spinnerX); |
| map.put("screenY", ScreenDimensions.spinnerY); |
| |
| int scaledWidth = (int)(Ampl_factor * ScreenDimensions.resizeX); |
| int scaledHeight = (int)(Ampl_factor * ScreenDimensions.resizeY); |
| |
| map.put("screenWidth", scaledWidth); |
| map.put("screenHeight", scaledHeight); |
| |
| map.put("publishName", this.publishName); |
| map.put("startRecording", startRecording); |
| map.put("startStreaming", startStreaming); |
| map.put("startPublishing", startPublishing); |
| map.put("publishingHost", frame.getPublishHost()); |
| map.put("publishingApp", frame.getPublishApp()); |
| map.put("publishingId", frame.getPublishId()); |
| |
| map.put("organization_id", this.organization_id); |
| map.put("user_id", this.user_id); |
| |
| instance.invoke("setConnectionAsSharingClient", new Object[] { map }, instance); |
| } catch (Exception err) { |
| logger.error("setConnectionAsSharingClient Exception: ", err); |
| frame.setStatus("Error: " + err.getLocalizedMessage()); |
| logger.error("[setConnectionAsSharingClient]", err); |
| } |
| } |
| |
| /** |
| * @param startStreaming flag denoting the streaming is started |
| * @param startRecording flag denoting the recording is started |
| */ |
| public void captureScreenStart(boolean startStreaming, boolean startRecording) { |
| captureScreenStart(startStreaming, startRecording, false); |
| } |
| |
| public void captureScreenStart(boolean startStreaming, boolean startRecording, boolean startPublishing) { |
| try { |
| logger.debug("captureScreenStart"); |
| this.startStreaming = startStreaming; |
| this.startRecording= startRecording; |
| this.startPublishing = startPublishing; |
| |
| if (!isConnected) { |
| instance.connect(host, port, app, instance); |
| } else { |
| setConnectionAsSharingClient(); |
| } |
| } catch (Exception err) { |
| logger.error("captureScreenStart Exception: ", err); |
| frame.setStatus("Exception: " + err); |
| } |
| } |
| |
| public void captureScreenStop(boolean stopStreaming, boolean stopRecording) { |
| captureScreenStop(stopStreaming, stopRecording, false); |
| } |
| |
| public void captureScreenStop(boolean stopStreaming, boolean stopRecording, boolean stopPublishing) { |
| try { |
| logger.debug("INVOKE screenSharerAction" ); |
| |
| Map<String, Object> map = new HashMap<String, Object>(); |
| map.put("stopStreaming", stopStreaming); |
| map.put("stopRecording", stopRecording); |
| map.put("stopPublishing", stopPublishing); |
| |
| instance.invoke("screenSharerAction", new Object[] { map }, instance); |
| |
| if (stopStreaming) { |
| frame.setSharingStatus(false); |
| } else if (stopRecording) { |
| frame.setRecordingStatus(false); |
| } else if (stopPublishing) { |
| frame.setPublishingStatus(false); |
| } |
| } catch (Exception err) { |
| logger.error("captureScreenStop Exception: ", err); |
| frame.setStatus("Exception: " + err); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // |
| // Public |
| // |
| // ------------------------------------------------------------------------ |
| |
| protected void onInvoke(RTMPConnection conn, Channel channel, |
| Header source, Notify invoke, RTMP rtmp) { |
| |
| if (invoke.getType() == IEvent.Type.STREAM_DATA) { |
| return; |
| } |
| |
| String method = invoke.getCall().getServiceMethodName(); |
| if ("sendRemoteCursorEvent".equals(method)) { |
| sendRemoteCursorEvent(invoke.getCall().getArguments()[0]); |
| } else if ("screenSharerAction".equals(method)) { |
| Object[] args = invoke.getCall().getArguments(); |
| if (args != null) { |
| @SuppressWarnings("unchecked") |
| HashMap<String, Object> params = (HashMap<String, Object>)args[0]; |
| if (params.containsKey("stopPublishing") |
| && Boolean.parseBoolean("" + params.get("stopPublishing"))) { |
| frame.setPublishingStatus(false); |
| } |
| if (params.containsKey("error")) { |
| frame.setStatus("" + params.get("error")); |
| } |
| } |
| } |
| } |
| |
| public void stopStream() { |
| try { |
| logger.debug("ScreenShare stopStream"); |
| |
| isConnected = false; |
| |
| instance.disconnect(); |
| capture.stop(); |
| capture.release(); |
| thread = null; |
| } catch (Exception e) { |
| logger.error("ScreenShare stopStream exception " + e); |
| } |
| |
| } |
| |
| public void onStreamEvent(Notify notify) { |
| |
| logger.debug( "onStreamEvent " + notify ); |
| |
| @SuppressWarnings("rawtypes") |
| ObjectMap map = (ObjectMap) notify.getCall().getArguments()[0]; |
| String code = (String) map.get("code"); |
| |
| if (StatusCodes.NS_PUBLISH_START.equals(code)) { |
| logger.debug( "onStreamEvent Publish start" ); |
| startPublish = true; |
| } |
| } |
| |
| public void sendRemoteCursorEvent(Object obj) { |
| try { |
| |
| // logger.debug("#### sendRemoteCursorEvent "); |
| |
| // logger.debug("Result Map Type "+obj.getClass().getName()); |
| |
| @SuppressWarnings("rawtypes") |
| Map returnMap = (Map) obj; |
| |
| // logger.debug("result "+returnMap.get("result")); |
| |
| String action = returnMap.get("action").toString(); |
| |
| if (action.equals("onmouseup")) { |
| |
| Robot robot = new Robot(); |
| |
| // VirtualScreenBean |
| |
| Float scaleFactor = Float |
| .valueOf(ScreenDimensions.spinnerWidth) |
| / Float.valueOf(ScreenDimensions.resizeX); |
| |
| // logger.debug("x 1 scaleFactor "+scaleFactor); |
| |
| Float part_x1 = ((Float.valueOf(returnMap.get("x").toString()) |
| .floatValue() * scaleFactor) / Float |
| .valueOf(Ampl_factor)); |
| |
| // logger.debug("x 1 part_x1 "+part_x1); |
| |
| Integer x = Math.round(part_x1 |
| + ScreenDimensions.spinnerX); |
| |
| Integer y = Math |
| .round(((Float.valueOf(returnMap.get("y").toString()) |
| .floatValue() |
| * ScreenDimensions.spinnerHeight / ScreenDimensions.resizeY) / Ampl_factor) |
| + ScreenDimensions.spinnerY); |
| |
| // logger.debug("x|y "+x+" || "+y); |
| |
| robot.mouseMove(x, y); |
| robot.mouseRelease(InputEvent.BUTTON1_MASK); |
| |
| } else if (action.equals("onmousedown")) { |
| |
| Robot robot = new Robot(); |
| |
| Float scaleFactor = Float |
| .valueOf(ScreenDimensions.spinnerWidth) |
| / Float.valueOf(ScreenDimensions.resizeX); |
| Float part_x1 = ((Float.valueOf(returnMap.get("x").toString()) |
| .floatValue() * scaleFactor) / Float |
| .valueOf(Ampl_factor)); |
| Integer x = Math.round(part_x1 |
| + ScreenDimensions.spinnerX); |
| Integer y = Math |
| .round(((Float.valueOf(returnMap.get("y").toString()) |
| .floatValue() |
| * ScreenDimensions.spinnerHeight / ScreenDimensions.resizeY) / Ampl_factor) |
| + ScreenDimensions.spinnerY); |
| |
| robot.mouseMove(x, y); |
| robot.mousePress(InputEvent.BUTTON1_MASK); |
| |
| } else if (action.equals("mousePos")) { |
| |
| Robot robot = new Robot(); |
| |
| Float scaleFactor = Float |
| .valueOf(ScreenDimensions.spinnerWidth) |
| / Float.valueOf(ScreenDimensions.resizeX); |
| |
| Float part_x1 = ((Float.valueOf(returnMap.get("x").toString()) |
| .floatValue() * scaleFactor) / Float |
| .valueOf(Ampl_factor)); |
| |
| Integer x = Math.round(part_x1 |
| + ScreenDimensions.spinnerX); |
| |
| Integer y = Math |
| .round(((Float.valueOf(returnMap.get("y").toString()) |
| .floatValue() |
| * ScreenDimensions.spinnerHeight / ScreenDimensions.resizeY) / Ampl_factor) |
| + ScreenDimensions.spinnerY); |
| |
| robot.mouseMove(x, y); |
| |
| } else if (action.equals("onkeydown")) { |
| |
| Robot robot = new Robot(); |
| |
| Integer key = Integer.valueOf(returnMap.get("k").toString()) |
| .intValue(); |
| |
| // logger.debug("key onkeydown -1 "+key); |
| boolean doAction = true; |
| |
| if (key == 221) { |
| key = 61; |
| } else if (key == -1) { |
| |
| String charValue = returnMap.get("c").toString(); |
| |
| // key = KeyEvent.VK_ADD; |
| doAction = false; |
| |
| for (Iterator<Integer> iter = this.currentPressedKeys |
| .keySet().iterator(); iter.hasNext();) { |
| Integer storedKey = iter.next(); |
| |
| robot.keyRelease(storedKey); |
| |
| } |
| |
| this.currentPressedKeys = new HashMap<Integer, Boolean>(); |
| |
| this.pressSpecialSign(charValue, robot); |
| } else if (key == 188) { |
| key = 44; |
| } else if (key == 189) { |
| key = 109; |
| } else if (key == 190) { |
| key = 46; |
| } else if (key == 191) { |
| key = 47; |
| } else if (key == 13) { |
| key = KeyEvent.VK_ENTER; |
| } |
| |
| // logger.debug("key onkeydown -2 "+key); |
| |
| if (doAction) { |
| |
| this.currentPressedKeys.put(key, true); |
| |
| robot.keyPress(key); |
| } |
| |
| } else if (action.equals("onkeyup")) { |
| |
| Robot robot = new Robot(); |
| |
| Integer key = Integer.valueOf(returnMap.get("k").toString()) |
| .intValue(); |
| |
| // logger.debug("key onkeyup 1- "+key); |
| |
| boolean doAction = true; |
| |
| if (key == 221) { |
| key = 61; |
| } else if (key == -1) { |
| doAction = false; |
| } else if (key == 188) { |
| key = 44; |
| } else if (key == 189) { |
| key = 109; |
| } else if (key == 190) { |
| key = 46; |
| } else if (key == 191) { |
| key = 47; |
| } else if (key == 13) { |
| key = KeyEvent.VK_ENTER; |
| } |
| |
| // logger.debug("key onkeyup 2- "+key); |
| |
| if (doAction) { |
| |
| if (this.currentPressedKeys.containsKey(key)) { |
| this.currentPressedKeys.remove(key); |
| |
| robot.keyRelease(key); |
| |
| } |
| |
| } |
| |
| } else if (action.equals("paste")) { |
| |
| Robot robot = new Robot(); |
| |
| String paste = returnMap.get("paste").toString(); |
| |
| this.pressSpecialSign(paste, robot); |
| |
| } else if (action.equals("copy")) { |
| |
| Robot robot = new Robot(); |
| |
| String paste = this.getHighlightedText(robot); |
| |
| HashMap<Integer, String> map = new HashMap<Integer, String>(); |
| map.put(0, "copiedText"); |
| map.put(1, paste); |
| |
| String clientId = returnMap.get("clientId").toString(); |
| |
| // public synchronized int sendMessageWithClientById(Object |
| // newMessage, String clientId) |
| |
| instance.invoke("sendMessageWithClientById", new Object[] { map, |
| clientId }, instance); |
| |
| } else if (action.equals("show")) { |
| |
| String paste = this.getClipboardText(); |
| |
| HashMap<Integer, String> map = new HashMap<Integer, String>(); |
| map.put(0, "copiedText"); |
| map.put(1, paste); |
| |
| String clientId = returnMap.get("clientId").toString(); |
| |
| // public synchronized int sendMessageWithClientById(Object |
| // newMessage, String clientId) |
| |
| instance.invoke("sendMessageWithClientById", new Object[] { map, |
| clientId }, instance); |
| |
| } |
| |
| // KeyEvent.VK |
| // KeyEvent. |
| |
| } catch (Exception err) { |
| logger.error("[sendRemoteCursorEvent]", err); |
| } |
| } |
| |
| public String getClipboardText() { |
| try { |
| // get the system clipboard |
| Clipboard systemClipboard = Toolkit.getDefaultToolkit() |
| .getSystemClipboard(); |
| |
| // get the contents on the clipboard in a |
| // transferable object |
| Transferable clipboardContents = systemClipboard.getContents(null); |
| |
| // check if clipboard is empty |
| if (clipboardContents == null) { |
| |
| // Clipboard is empty!!! |
| return (""); |
| |
| // see if DataFlavor of |
| // DataFlavor.stringFlavor is supported |
| } else if (clipboardContents |
| .isDataFlavorSupported(DataFlavor.stringFlavor)) { |
| |
| // return text content |
| String returnText = (String) clipboardContents |
| .getTransferData(DataFlavor.stringFlavor); |
| |
| return returnText; |
| } |
| |
| return ""; |
| } catch (UnsupportedFlavorException ufe) { |
| ufe.printStackTrace(); |
| } catch (IOException ioe) { |
| ioe.printStackTrace(); |
| } |
| return ""; |
| } |
| |
| private String getHighlightedText(Robot instance) { |
| |
| try { |
| |
| // clippy.setContents( selection,selection ); |
| |
| // logger.debug("os.name :: "+System.getProperty("os.name")); |
| |
| if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) { |
| |
| // logger.debug("IS WINDOWS"); |
| |
| // pressing STRG+C == copy |
| instance.keyPress(KeyEvent.VK_CONTROL); |
| Thread.sleep(200); |
| instance.keyPress(KeyEvent.VK_C); |
| Thread.sleep(200); |
| instance.keyRelease(KeyEvent.VK_C); |
| Thread.sleep(200); |
| instance.keyRelease(KeyEvent.VK_CONTROL); |
| Thread.sleep(200); |
| |
| } else { |
| |
| // logger.debug("IS MAC"); |
| |
| // Macintosh simulate Copy |
| instance.keyPress(157); |
| Thread.sleep(200); |
| instance.keyPress(67); |
| Thread.sleep(200); |
| instance.keyRelease(67); |
| Thread.sleep(200); |
| instance.keyRelease(157); |
| Thread.sleep(200); |
| |
| } |
| |
| String charValue = this.getClipboardText(); |
| |
| return charValue; |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return ""; |
| } |
| |
| private void pressSpecialSign(String charValue, Robot instance) { |
| Clipboard clippy = Toolkit.getDefaultToolkit().getSystemClipboard(); |
| try { |
| |
| Transferable transferableText = new StringSelection(charValue); |
| clippy.setContents(transferableText, null); |
| |
| // logger.debug("os.name :: "+System.getProperty("os.name")); |
| |
| if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) { |
| |
| // logger.debug("IS WINDOWS"); |
| |
| // pressing STRG+V == insert-mode |
| instance.keyPress(KeyEvent.VK_CONTROL); |
| Thread.sleep(100); |
| instance.keyPress(KeyEvent.VK_V); |
| Thread.sleep(100); |
| instance.keyRelease(KeyEvent.VK_V); |
| Thread.sleep(100); |
| instance.keyRelease(KeyEvent.VK_CONTROL); |
| Thread.sleep(100); |
| |
| } else { |
| |
| // logger.debug("IS MAC"); |
| |
| // Macintosh simulate Insert |
| instance.keyPress(157); |
| Thread.sleep(100); |
| instance.keyPress(86); |
| Thread.sleep(100); |
| instance.keyRelease(86); |
| Thread.sleep(100); |
| instance.keyRelease(157); |
| Thread.sleep(100); |
| |
| } |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| public void resultReceived(IPendingServiceCall call) { |
| try { |
| |
| logger.trace( "service call result: " + call ); |
| |
| if (call.getServiceMethodName().equals("connect")) { |
| isConnected = true; |
| setConnectionAsSharingClient(); |
| } else if (call.getServiceMethodName().equals( |
| "setConnectionAsSharingClient")) { |
| |
| Object o = call.getResult(); |
| |
| @SuppressWarnings("rawtypes") |
| Map returnMap = (Map) o; |
| |
| if (o == null || !Boolean.valueOf("" + returnMap.get("alreadyPublished")).booleanValue()) { |
| logger.trace("Stream not yet started - do it "); |
| |
| instance.createStream(instance); |
| } else { |
| if (this.capture != null) { |
| this.capture.resetBuffer(); |
| } |
| |
| logger.trace("The Stream was already started "); |
| } |
| |
| if (returnMap != null) { |
| Object modus = returnMap.get("modus"); |
| if ("startStreaming".equals(modus)) { |
| frame.setSharingStatus(true); |
| } else if ("startRecording".equals(modus)) { |
| frame.setRecordingStatus(true); |
| } else if ("startPublishing".equals(modus)) { |
| frame.setPublishingStatus(true); |
| } |
| } else { |
| throw new Exception( |
| "Could not aquire modus for event setConnectionAsSharingClient"); |
| } |
| |
| } else if (call.getServiceMethodName().equals("createStream")) { |
| |
| publishStreamId = (Integer) call.getResult(); |
| logger.debug("createPublishStream result stream id: " |
| + publishStreamId); |
| logger.debug("publishing video by name: " + publishName); |
| instance.publish(publishStreamId, publishName, "live", instance); |
| |
| logger.debug("setup capture thread"); |
| |
| logger.debug("setup capture thread vScreenSpinnerWidth " |
| + ScreenDimensions.spinnerWidth); |
| logger.debug("setup capture thread vScreenSpinnerHeight " |
| + ScreenDimensions.spinnerHeight); |
| |
| capture = new CaptureScreen(); |
| |
| if (thread == null) { |
| thread = new Thread(capture); |
| thread.start(); |
| } |
| capture.start(); |
| |
| } else if (call.getServiceMethodName().equals("screenSharerAction")) { |
| logger.trace("call ### get Method Name " |
| + call.getServiceMethodName()); |
| |
| Object o = call.getResult(); |
| |
| logger.trace("Result Map Type " + o.getClass().getName()); |
| |
| @SuppressWarnings("unchecked") |
| Map<String, Object> returnMap = (Map<String, Object>)o; |
| Object result = returnMap.get("result"); |
| if ("stopAll".equals(result)) { |
| logger.trace("Stopping to stream, there is neither a Desktop Sharing nor Recording anymore"); |
| stopStream(); |
| } else if ("stopSharingOnly".equals(result)) { |
| //no op |
| } else if ("stopRecordingOnly".equals(result)) { |
| //no op |
| } else if ("stopPublishingOnly".equals(result)) { |
| frame.setPublishingStatus(false); |
| } |
| } else if (call.getServiceMethodName().equals( |
| "setNewCursorPosition")) { |
| |
| // Do not do anything |
| |
| } else { |
| |
| logger.debug("Unknown method " + call.getServiceMethodName()); |
| |
| } |
| |
| } catch (Exception err) { |
| logger.error("[resultReceived]", err); |
| } |
| } |
| |
| public void pushVideo(int len, byte[] video, long ts) throws IOException { |
| |
| if (!startPublish) |
| return; |
| |
| if (buffer == null || (buffer.capacity() < video.length && !buffer.isAutoExpand())) { |
| buffer = IoBuffer.allocate(video.length); |
| buffer.setAutoExpand(true); |
| } |
| |
| buffer.clear(); |
| buffer.put(video); |
| buffer.flip(); |
| |
| VideoData videoData = new VideoData(buffer); |
| videoData.setTimestamp((int) ts); |
| |
| RTMPMessage rtmpMsg = RTMPMessage.build(videoData); |
| instance.publishStreamData(publishStreamId, rtmpMsg); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // |
| // CaptureScreen |
| // |
| // ------------------------------------------------------------------------ |
| |
| private final class CaptureScreen extends Object implements Runnable { |
| private int timeBetweenFrames = 500; // frameRate |
| private volatile long timestamp = 0; |
| private volatile boolean active = true; |
| @SuppressWarnings("unused") |
| private volatile boolean stopped = false; |
| private IScreenEncoder se; |
| |
| // ------------------------------------------------------------------------ |
| // |
| // Constructor |
| // |
| // ------------------------------------------------------------------------ |
| |
| public CaptureScreen() { |
| timeBetweenFrames = (ScreenDimensions.quality == ScreenQuality.VeryHigh) ? 100 : 500; |
| se = new ScreenV1Encoder(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // |
| // Public |
| // |
| // ------------------------------------------------------------------------ |
| public void start() { |
| stopped = false; |
| } |
| |
| public void stop() { |
| stopped = true; |
| } |
| |
| public void release() { |
| active = false; |
| } |
| |
| public void resetBuffer() { |
| se.reset(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // |
| // Thread loop |
| // |
| // ------------------------------------------------------------------------ |
| public void run() { |
| try { |
| Robot robot = new Robot(); |
| BufferedImage image = null; |
| while (active) { |
| final long ctime = System.currentTimeMillis(); |
| Rectangle screen = new Rectangle(ScreenDimensions.spinnerX, |
| ScreenDimensions.spinnerY, |
| ScreenDimensions.spinnerWidth, |
| ScreenDimensions.spinnerHeight); |
| |
| image = robot.createScreenCapture(screen); |
| |
| try { |
| timestamp += timeBetweenFrames; |
| byte[] data = se.encode(screen, image, new Rectangle(ScreenDimensions.resizeX, |
| ScreenDimensions.resizeY)); |
| |
| pushVideo(data.length, data, timestamp); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| final int spent = (int) (System.currentTimeMillis() - ctime); |
| |
| sendCursorStatus(); |
| |
| Thread.sleep(Math.max(0, timeBetweenFrames - spent)); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |