Java tutorial
/* * 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.app.remote.red5; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.openmeetings.app.OpenmeetingsVariables; import org.openmeetings.app.conference.session.RoomClient; import org.openmeetings.app.conference.whiteboard.BrowserStatus; import org.openmeetings.app.conference.whiteboard.RoomStatus; import org.openmeetings.app.conference.whiteboard.WhiteboardManagement; import org.openmeetings.app.data.basic.Configurationmanagement; import org.openmeetings.app.data.basic.Sessionmanagement; import org.openmeetings.app.data.calendar.daos.MeetingMemberDaoImpl; import org.openmeetings.app.data.calendar.management.AppointmentLogic; import org.openmeetings.app.data.conference.Roommanagement; import org.openmeetings.app.data.logs.ConferenceLogDaoImpl; import org.openmeetings.app.data.user.Usermanagement; import org.openmeetings.app.data.user.dao.UsersDaoImpl; import org.openmeetings.app.persistence.beans.basic.Configuration; import org.openmeetings.app.persistence.beans.calendar.Appointment; import org.openmeetings.app.persistence.beans.calendar.MeetingMember; import org.openmeetings.app.persistence.beans.rooms.Rooms; import org.openmeetings.app.persistence.beans.user.Users; import org.openmeetings.app.remote.FLVRecorderService; import org.openmeetings.app.remote.WhiteBoardService; import org.openmeetings.utils.math.CalendarPatterns; import org.red5.client.net.rtmp.ClientExceptionHandler; import org.red5.logging.Red5LoggerFactory; import org.red5.server.adapter.ApplicationAdapter; import org.red5.server.api.IClient; import org.red5.server.api.IConnection; import org.red5.server.api.Red5; import org.red5.server.api.scope.IBasicScope; import org.red5.server.api.scope.IBroadcastScope; import org.red5.server.api.scope.IScope; import org.red5.server.api.scope.ScopeType; import org.red5.server.api.service.IPendingServiceCall; import org.red5.server.api.service.IPendingServiceCallback; import org.red5.server.api.service.IServiceCapableConnection; import org.red5.server.api.stream.IBroadcastStream; import org.red5.server.api.stream.IStreamListener; import org.red5.server.api.stream.IStreamPacket; import org.red5.server.net.rtmp.event.IRTMPEvent; import org.red5.server.stream.StreamingProxy; import org.red5.server.stream.message.RTMPMessage; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; public class ScopeApplicationAdapter extends ApplicationAdapter implements IPendingServiceCallback { private static final Logger log = Red5LoggerFactory.getLogger(ScopeApplicationAdapter.class, OpenmeetingsVariables.webAppRootKey); @Autowired private ClientListManager clientListManager; @Autowired private EmoticonsManager emoticonsManager; @Autowired private WhiteBoardService whiteBoardService; @Autowired private FLVRecorderService flvRecorderService; @Autowired private Configurationmanagement cfgManagement; @Autowired private AppointmentLogic appointmentLogic; @Autowired private Sessionmanagement sessionManagement; @Autowired private Usermanagement userManagement; @Autowired private Roommanagement roommanagement; @Autowired private ConferenceLogDaoImpl conferenceLogDao; @Autowired private UsersDaoImpl usersDao; @Autowired private MeetingMemberDaoImpl meetingMemberDao; private Map<String, StreamingProxy> streamingProxyMap = new HashMap<String, StreamingProxy>(); // This is the Folder where all executables are written // for windows platform public static String batchFileDir = "webapps" + File.separatorChar + "ROOT" + File.separatorChar + "jod" + File.separatorChar; public static String lineSeperator = System.getProperty("line.separator"); // The Global WebApp Path public static String webAppPath = ""; public static String configDirName = "conf"; public static String profilesPrefix = "profile_"; public static String configKeyCryptClassName = null; public static Boolean whiteboardDrawStatus = null; private static long broadCastCounter = 0; public static boolean initComplete = false; public synchronized void resultReceived(IPendingServiceCall arg0) { // TODO Auto-generated method stub } @Override public synchronized boolean appStart(IScope scope) { try { webAppPath = scope.getResource("/").getFile().getAbsolutePath(); batchFileDir = webAppPath + File.separatorChar + OpenmeetingsVariables.STREAMS_DIR + File.separatorChar; log.debug("webAppPath : " + webAppPath); log.debug("batchFileFir : " + batchFileDir); // Only load this Class one time // Initially this value might by empty, because the DB is empty yet Configuration conf = cfgManagement.getConfKey(3, "crypt_ClassName"); if (conf != null) { ScopeApplicationAdapter.configKeyCryptClassName = conf.getConf_value(); } // init your handler here // The scheduled Jobs did go into the Spring-Managed Beans, see // schedulerJobs.service.xml // Spring Definition does not work here, its too early, Instance is // not set yet emoticonsManager.loadEmot(scope); for (String scopeName : scope.getScopeNames()) { log.debug("scopeName :: " + scopeName); } ScopeApplicationAdapter.initComplete = true; clientListManager.removeAllClients(); // OpenXGHttpClient.getInstance().openSIPgUserCreateTest(); // OpenXGWrapperClient.getInstance().testConnection(); // OpenXGClient.getInstance().testConnection(); // ServerSocketMinaProcess serverSocketMinaProcess = new // ServerSocketMinaProcess(); // serverSocketMinaProcess.doInitSocket(); } catch (Exception err) { log.error("[appStart]", err); } return true; } @Override public boolean roomConnect(IConnection conn, Object[] params) { log.debug("roomConnect : "); try { IServiceCapableConnection service = (IServiceCapableConnection) conn; String streamId = conn.getClient().getId(); boolean isAVClient = false; if (params.length == 1) { isAVClient = Boolean.parseBoolean(params[0].toString()); } log.debug("### Client connected to OpenMeetings, register Client StreamId: " + streamId + " scope " + conn.getScope().getName() + " isAVClient " + isAVClient); log.debug("params " + params); // Set StreamId in Client service.invoke("setId", new Object[] { streamId }, this); String swfURL = ""; if (conn.getConnectParams().get("swfUrl") != null) { swfURL = conn.getConnectParams().get("swfUrl").toString(); } RoomClient rcm = this.clientListManager.addClientListItem(streamId, conn.getScope().getName(), conn.getRemotePort(), conn.getRemoteAddress(), swfURL, isAVClient); // Log the User conferenceLogDao.addConferenceLog("ClientConnect", rcm.getUser_id(), streamId, null, rcm.getUserip(), rcm.getScope(), rcm.getExternalUserId(), rcm.getExternalUserType(), rcm.getMail(), rcm.getFirstname(), rcm.getLastname()); } catch (Exception err) { log.error("roomJoin", err); } return true; } @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized Map screenSharerAction(Map map) { try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); Map returnMap = new HashMap(); returnMap.put("result", "stopAll"); log.debug("----------- "); if (currentClient != null) { if (Boolean.valueOf(map.get("stopStreaming").toString())) { log.debug("start streamPublishStart Is Screen Sharing -- Stop "); //Send message to all users syncMessageToCurrentScope("stopRed5ScreenSharing", currentClient, false); if (currentClient.isStartRecording()) { returnMap.put("result", "stopSharingOnly"); } currentClient.setStartStreaming(false); currentClient.setScreenPublishStarted(false); clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); } if (Boolean.valueOf(map.get("stopRecording").toString())) { if (currentClient.isStartStreaming()) { returnMap.put("result", "stopRecordingOnly"); } //Send message to all users syncMessageToCurrentScope("stopRecordingMessage", currentClient, false); flvRecorderService.stopRecordAndSave(current.getScope(), currentClient, null); currentClient.setStartRecording(false); currentClient.setIsRecording(false); clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); } if (Boolean.valueOf(map.get("stopPublishing").toString())) { streamPublishingStop(); if (currentClient.getIsScreenClient() && currentClient.isStartStreaming()) { returnMap.put("result", "stopPublishingOnly"); } } } return returnMap; } catch (Exception err) { log.error("[screenSharerAction]", err); } return null; } public List<RoomClient> checkRed5ScreenSharing() { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); log.debug("checkScreenSharing -2- " + streamid); List<RoomClient> screenSharerList = new LinkedList<RoomClient>(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); HashMap<String, RoomClient> roomList = this.clientListManager .getClientListByRoomAll(currentClient.getRoom_id()); for (Iterator<String> iter = roomList.keySet().iterator(); iter.hasNext();) { RoomClient rcl = roomList.get(iter.next()); if (rcl.isStartStreaming()) { screenSharerList.add(rcl); } } return screenSharerList; } catch (Exception err) { log.error("[checkScreenSharing]", err); } return null; } @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized Map setConnectionAsSharingClient(Map map) { try { IConnection current = Red5.getConnectionLocal(); // IServiceCapableConnection service = (IServiceCapableConnection) // current; log.debug("### setConnectionAsSharingClient: "); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); if (currentClient != null) { boolean startRecording = Boolean.valueOf(map.get("startRecording").toString()); boolean startStreaming = Boolean.valueOf(map.get("startStreaming").toString()); currentClient.setRoom_id(Long.parseLong(current.getScope().getName())); // Set this connection to be a RTMP-Java Client currentClient.setIsScreenClient(true); currentClient.setUser_id(Long.parseLong(map.get("user_id").toString())); if (startStreaming) { currentClient.setStartStreaming(true); } if (startRecording) { currentClient.setStartRecording(true); } currentClient.setOrganization_id(Long.parseLong(map.get("organization_id").toString())); this.clientListManager.updateClientByStreamId(current.getClient().getId(), currentClient); Map returnMap = new HashMap(); returnMap.put("alreadyPublished", false); // if is already started screen sharing, then there is no need // to start it again if (currentClient.isScreenPublishStarted()) { returnMap.put("alreadyPublished", true); } currentClient.setVX(Integer.parseInt(map.get("screenX").toString())); currentClient.setVY(Integer.parseInt(map.get("screenY").toString())); currentClient.setVWidth(Integer.parseInt(map.get("screenWidth").toString())); currentClient.setVHeight(Integer.parseInt(map.get("screenHeight").toString())); log.debug("screen x,y,width,height " + currentClient.getVX() + " " + currentClient.getVY() + " " + currentClient.getVWidth() + " " + currentClient.getVHeight()); log.debug("publishName :: " + map.get("publishName")); currentClient.setStreamPublishName(map.get("publishName").toString()); RoomClient currentScreenUser = this.clientListManager .getClientByPublicSID(currentClient.getStreamPublishName(), false); currentClient.setFirstname(currentScreenUser.getFirstname()); currentClient.setLastname(currentScreenUser.getLastname()); // This is duplicated, but its not sure that in the meantime // somebody requests this Client Object Info this.clientListManager.updateClientByStreamId(current.getClient().getId(), currentClient); if (startStreaming) { returnMap.put("modus", "startStreaming"); log.debug("start streamPublishStart Is Screen Sharing "); //Send message to all users syncMessageToCurrentScope("newRed5ScreenSharing", currentClient, false); } else if (startRecording) { returnMap.put("modus", "startRecording"); String recordingName = "Recording " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date()); flvRecorderService.recordMeetingStream(recordingName, "", false); } else if (Boolean.valueOf(map.get("startPublishing").toString())) { if (streamPublishingStart("" + map.get("publishingHost"), "" + map.get("publishingApp"), "" + map.get("publishingId"))) { returnMap.put("modus", "startPublishing"); } } return returnMap; } else { throw new Exception("Could not find Screen Sharing Client " + current.getClient().getId()); } } catch (Exception err) { log.error("[setConnectionAsSharingClient]", err); } return null; } public synchronized List<Integer> listRoomBroadcast() { List<Integer> broadcastList = new ArrayList<Integer>(); IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { if (!streamid.equals(rcl.getStreamid())) { // It is not needed to send back // that event to the actuall // Moderator // as it will be already triggered // in the result of this Function // in the Client broadcastList.add(Long.valueOf(rcl.getBroadCastID()).intValue()); } } } } } return broadcastList; } /** * this function is invoked directly after initial connecting * * @return */ public synchronized String getPublicSID() { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); currentClient.setIsAVClient(false); clientListManager.updateClientByStreamId(current.getClient().getId(), currentClient); return currentClient.getPublicSID(); } /** * this function is invoked after a reconnect * * @param newPublicSID */ public synchronized Boolean overwritePublicSID(String newPublicSID) { try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); if (currentClient == null) { return false; } currentClient.setPublicSID(newPublicSID); this.clientListManager.updateClientByStreamId(current.getClient().getId(), currentClient); return true; } catch (Exception err) { log.error("[overwritePublicSID]", err); } return null; } /** * Logic must be before roomDisconnect cause otherwise you cannot throw a * message to each one * */ @Override public void roomLeave(IClient client, IScope room) { try { log.debug("roomLeave " + client.getId() + " " + room.getClients().size() + " " + room.getContextPath() + " " + room.getName()); RoomClient currentClient = this.clientListManager.getClientByStreamId(client.getId()); // The Room Client can be null if the Client left the room by using // logicalRoomLeave if (currentClient != null) { log.debug("currentClient IS NOT NULL"); this.roomLeaveByScope(currentClient, room, true); } } catch (Exception err) { log.error("[roomLeave]", err); } } /** * this means a user has left a room but only logically, he didn't leave the * app he just left the room * * FIXME: Is this really needed anymore if you re-connect to another scope? * * Exit Room by Application * */ public synchronized void logicalRoomLeave() { log.debug("logicalRoomLeave "); try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); log.debug(streamid + " is leaving"); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); this.roomLeaveByScope(currentClient, current.getScope(), true); } catch (Exception err) { log.error("[logicalRoomLeave]", err); } } /** * Removes the Client from the List, stops recording, adds the Room-Leave * event to running recordings, clear Polls and removes Client from any list * * This function is kind of private/protected as the client won't be able * to call it with proper values. * * @param currentClient * @param currentScope */ public synchronized void roomLeaveByScope(RoomClient currentClient, IScope currentScope, boolean removeUserFromSessionList) { try { log.debug("currentClient " + currentClient); log.debug("currentScope " + currentScope); // log.debug("currentClient "+currentClient.getRoom_id()); Long room_id = currentClient.getRoom_id(); // Log the User conferenceLogDao.addConferenceLog("roomLeave", currentClient.getUser_id(), currentClient.getStreamid(), room_id, currentClient.getUserip(), "", currentClient.getExternalUserId(), currentClient.getExternalUserType(), currentClient.getMail(), currentClient.getFirstname(), currentClient.getLastname()); // Remove User from Sync List's if (room_id != null) { this.whiteBoardService.removeUserFromAllLists(currentScope, currentClient); } log.debug("removing USername " + currentClient.getUsername() + " " + currentClient.getConnectedSince() + " streamid: " + currentClient.getStreamid()); // stop and save any recordings if (currentClient.getIsRecording()) { log.debug("*** roomLeave Current Client is Recording - stop that"); // StreamService.stopRecordAndSave(currentScope, // currentClient.getRoomRecordingName(), currentClient); this.flvRecorderService.stopRecordAndSave(currentScope, currentClient, null); // set to true and overwrite the default one cause otherwise no // notification is send currentClient.setIsRecording(true); } // Notify all clients of the same currentScope (room) with domain // and room except the current disconnected cause it could throw an exception log.debug("currentScope " + currentScope); if (currentScope != null && currentScope.getConnections() != null) { // Notify Users of the current Scope Collection<Set<IConnection>> conCollection = currentScope.getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection cons : conset) { if (cons != null) { if (cons instanceof IServiceCapableConnection) { log.debug("sending roomDisconnect to " + cons + " client id " + cons.getClient().getId()); RoomClient rcl = this.clientListManager .getClientByStreamId(cons.getClient().getId()); /* * Check if the Client does still exist on the * list */ if (rcl != null) { /* * Do not send back to sender, but actually * all other clients should receive this * message swagner 01.10.2009 */ if (!currentClient.getStreamid().equals(rcl.getStreamid())) { // add Notification if another user isrecording log.debug("###########[roomLeave]"); if (rcl.getIsRecording()) { log.debug("*** roomLeave Any Client is Recording - stop that"); this.flvRecorderService.stopRecordingShowForClient(cons, currentClient); } //If the user was a avclient, we do not broadcast a message about that to everybody if (currentClient.getIsAVClient()) { continue; } if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // screen sharing clients do not receive events continue; } else if (rcl.getIsAVClient()) { // AVClients or potential AVClients do not receive events continue; } // Send to all connected users ((IServiceCapableConnection) cons).invoke("roomDisconnect", new Object[] { currentClient }, this); log.debug("sending roomDisconnect to " + cons); } } else { log.debug("For this StreamId: " + cons.getClient().getId() + " There is no Client in the List anymore"); } } } } } } if (removeUserFromSessionList) { this.clientListManager.removeClient(currentClient.getStreamid()); } } catch (Exception err) { log.error("[roomLeaveByScope]", err); } } /** * This method handles the Event after a stream has been added all connected * Clients in the same room will get a notification * * @return void * */ @Override public synchronized void streamPublishStart(IBroadcastStream stream) { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); //We make a second object the has the reference to the object //that we will use to send to all participents RoomClient clientObjectSendToSync = currentClient; // Notify all the clients that the stream had been started log.debug( "start streamPublishStart broadcast start: " + stream.getPublishedName() + " CONN " + current); // In case its a screen sharing we start a new Video for that if (currentClient.getIsScreenClient()) { currentClient.setScreenPublishStarted(true); this.clientListManager.updateClientByStreamId(current.getClient().getId(), currentClient); } //If its an audio/video client then send the session object with the full //data to everybody else if (currentClient.getIsAVClient()) { clientObjectSendToSync = this.clientListManager.getClientByPublicSID(currentClient.getPublicSID(), false); } log.debug("newStream SEND: " + currentClient); // Notify all users of the same Scope // We need to iterate through the streams to catch if anybody is recording Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { log.debug("RCL IS NULL newStream SEND"); continue; } log.debug("check send to " + rcl); if (rcl.getPublicSID() == "") { log.debug("publicSID IS NULL newStream SEND"); continue; } if (rcl.getIsRecording()) { log.debug("RCL getIsRecording newStream SEND"); this.flvRecorderService.addRecordingByStreamId(current, streamid, currentClient, rcl.getFlvRecordingId()); } if (rcl.getIsAVClient()) { log.debug("RCL getIsAVClient newStream SEND"); continue; } if (rcl.getIsScreenClient() == null || rcl.getIsScreenClient()) { log.debug("RCL getIsScreenClient newStream SEND"); continue; } if (rcl.getPublicSID().equals(currentClient.getPublicSID())) { log.debug("RCL publicSID is equal newStream SEND"); continue; } log.debug("RCL SEND is equal newStream SEND " + rcl.getPublicSID() + " || " + rcl.getUserport()); IServiceCapableConnection iStream = (IServiceCapableConnection) conn; iStream.invoke("newStream", new Object[] { clientObjectSendToSync }, this); } } } } } catch (Exception err) { log.error("[streamPublishStart]", err); } } public IBroadcastScope getBroadcastScope(IScope scope, String name) { IBasicScope basicScope = scope.getBasicScope(ScopeType.BROADCAST, name); if (!(basicScope instanceof IBroadcastScope)) { return null; } else { return (IBroadcastScope) basicScope; } } public boolean streamPublishingStart(String host, String app, String id) { final boolean[] result = { true }; final IConnection conn = Red5.getConnectionLocal(); RoomClient rc = clientListManager.getClientByStreamId(conn.getClient().getId()); String publishName = rc.getStreamPublishName(); if (rc.getIsScreenClient() && rc.isStartStreaming()) { IScope scope = conn.getScope(); IBroadcastStream stream = getBroadcastStream(scope, publishName); IBroadcastScope bsScope = getBroadcastScope(scope, publishName); final StreamingProxy proxy = new StreamingProxy(); proxy.setHost(host); proxy.setApp(app); proxy.setPort(1935); proxy.init(); proxy.setExceptionHandler(new ClientExceptionHandler() { public void handleException(Throwable throwable) { result[0] = false; HashMap<String, Object> params = new HashMap<String, Object>(); params.put("stopPublishing", true); params.put("error", throwable.getMessage()); ((IServiceCapableConnection) conn).invoke("screenSharerAction", new Object[] { params }, ScopeApplicationAdapter.this); } }); bsScope.subscribe(proxy, null); proxy.start(id, "live", null); streamingProxyMap.put(publishName, proxy); stream.addStreamListener(new IStreamListener() { public void packetReceived(IBroadcastStream stream, IStreamPacket packet) { try { RTMPMessage m = RTMPMessage.build((IRTMPEvent) packet, packet.getTimestamp()); proxy.pushMessage(null, m); } catch (Exception e) { log.error("Exception while sending proxy message", e); } } }); } return result[0]; } public void streamPublishingStop() { IConnection current = Red5.getConnectionLocal(); RoomClient rc = clientListManager.getClientByStreamId(current.getClient().getId()); String publishName = rc.getStreamPublishName(); if (rc.getIsScreenClient() && publishName != null) { IScope scope = current.getScope(); IBroadcastStream stream = getBroadcastStream(scope, publishName); StreamingProxy proxy = streamingProxyMap.remove(publishName); if (proxy != null) { proxy.stop(); IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName()); if (bsScope != null) { bsScope.unsubscribe(proxy); } } } } /** * This method handles the Event after a stream has been removed all * connected Clients in the same room will get a notification * * @return void * */ @Override public synchronized void streamBroadcastClose(IBroadcastStream stream) { // Notify all the clients that the stream had been closed log.debug("start streamBroadcastClose broadcast close: " + stream.getPublishedName()); try { streamPublishingStop(); IConnection current = Red5.getConnectionLocal(); RoomClient rcl = clientListManager.getClientByStreamId(current.getClient().getId()); sendClientBroadcastNotifications(stream, "closeStream", rcl); } catch (Exception e) { log.error("[streamBroadcastClose]", e); } } /** * This method handles the notification room-based * * @return void * */ private synchronized void sendClientBroadcastNotifications(IBroadcastStream stream, String clientFunction, RoomClient rc) { try { // Store the local so that we do not send notification to ourself // back IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); if (currentClient == null) { // In case the client has already left(kicked) this message // might be thrown later then the RoomLeave // event and the currentClient is already gone // The second Use-Case where the currentClient is maybe null is // if we remove the client because its a Zombie/Ghost return; } // Notify all the clients that the stream had been started log.debug("sendClientBroadcastNotifications: " + stream.getPublishedName()); log.debug("sendClientBroadcastNotifications : " + currentClient + " " + currentClient.getStreamid()); // Notify all clients of the same scope (room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { if (conn.equals(current)) { // there is a Bug in the current implementation // of the appDisconnect if (clientFunction.equals("closeStream")) { RoomClient rcl = this.clientListManager .getClientByStreamId(conn.getClient().getId()); if (clientFunction.equals("closeStream") && rcl.getIsRecording()) { log.debug( "*** stopRecordingShowForClient Any Client is Recording - stop that"); // StreamService.stopRecordingShowForClient(conn, // currentClient, // rcl.getRoomRecordingName(), false); this.flvRecorderService.stopRecordingShowForClient(conn, currentClient); } // Don't notify current client current.ping(); } continue; } else { RoomClient rcl = this.clientListManager .getClientByStreamId(conn.getClient().getId()); if (rcl != null) { if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { log.debug("is this users still alive? :" + rcl); // conn.ping(); IServiceCapableConnection iStream = (IServiceCapableConnection) conn; // log.info("IServiceCapableConnection ID " // + iStream.getClient().getId()); iStream.invoke(clientFunction, new Object[] { rc }, this); } log.debug("sending notification to " + conn + " ID: "); // if this close stream event then stop the // recording of this stream if (clientFunction.equals("closeStream") && rcl.getIsRecording()) { log.debug( "*** +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that"); // StreamService.stopRecordingShowForClient(conn, // currentClient, // rcl.getRoomRecordingName(), false); this.flvRecorderService.stopRecordingShowForClient(conn, currentClient); } } } } } } } } catch (Exception err) { log.error("[sendClientBroadcastNotifications]", err); } } /** * Adds a Moderator by its publicSID * * @param publicSID * @return */ public synchronized Long addModerator(String publicSID) { try { log.debug("*..*addModerator publicSID: " + publicSID); // String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return -1L; } Long room_id = currentClient.getRoom_id(); currentClient.setIsMod(true); // Put the mod-flag to true for this client this.clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); List<RoomClient> currentMods = this.clientListManager.getCurrentModeratorByRoom(room_id); //Send message to all users syncMessageToCurrentScope("setNewModeratorByList", currentMods, true); } catch (Exception err) { log.error("[addModerator]", err); } return -1L; } @SuppressWarnings("unchecked") public void setNewCursorPosition(Object item) { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); // log.debug("[setNewCursorPosition]"+item); @SuppressWarnings("rawtypes") Map cursor = (Map) item; cursor.put("streamPublishName", currentClient.getStreamPublishName()); // log.debug("[setNewCursorPosition x]"+cursor.get("cursor_x")); // log.debug("[setNewCursorPosition y]"+cursor.get("cursor_y")); // log.debug("[setNewCursorPosition publicSID]"+cursor.get("publicSID")); // Notify all users of the same Scope Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { if (conn.equals(current)) { continue; } else { RoomClient rcl = this.clientListManager .getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { // log.debug("is this users still alive? :"+rcl); // Check if the Client is in the same room // and same domain IServiceCapableConnection iStream = (IServiceCapableConnection) conn; // log.info("IServiceCapableConnection ID " // + iStream.getClient().getId()); iStream.invoke("newRed5ScreenCursor", new Object[] { cursor }, this); // log.debug("send Notification to"); } } } } } } } catch (Exception err) { log.error("[setNewCursorPosition]", err); } } public synchronized Long removeModerator(String publicSID) { try { log.debug("*..*addModerator publicSID: " + publicSID); IConnection current = Red5.getConnectionLocal(); // String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return -1L; } Long room_id = currentClient.getRoom_id(); currentClient.setIsMod(false); // Put the mod-flag to true for this client this.clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); List<RoomClient> currentMods = this.clientListManager.getCurrentModeratorByRoom(room_id); // Notify all clients of the same scope (room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { log.debug("Send Flag to Client: " + rcl.getUsername()); if (conn instanceof IServiceCapableConnection) { ((IServiceCapableConnection) conn).invoke("setNewModeratorByList", new Object[] { currentMods }, this); log.debug("sending setNewModeratorByList to " + conn); } } } } } } catch (Exception err) { log.error("[addModerator]", err); } return -1L; } public synchronized Long setBroadCastingFlag(String publicSID, boolean value, Integer interviewPodId) { try { log.debug("*..*setBroadCastingFlag publicSID: " + publicSID); IConnection current = Red5.getConnectionLocal(); // String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return -1L; } currentClient.setIsBroadcasting(value); currentClient.setInterviewPodId(interviewPodId); // Put the mod-flag to true for this client this.clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); // Notify all clients of the same scope (room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { continue; } else if (rcl.getIsAVClient()) { continue; } log.debug("Send Flag to Client: " + rcl.getUsername()); if (conn instanceof IServiceCapableConnection) { ((IServiceCapableConnection) conn).invoke("setNewBroadCastingFlag", new Object[] { currentClient }, this); log.debug("sending setNewBroadCastingFlag to " + conn); } } } } } catch (Exception err) { log.error("[setBroadCastingFlag]", err); } return -1L; } public synchronized Long giveExclusiveAudio(String publicSID) { try { log.debug("*..*giveExclusiveAudio publicSID: " + publicSID); IConnection current = Red5.getConnectionLocal(); // String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return -1L; } // Put the mod-flag to true for this client currentClient.setMicMuted(false); this.clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); // Notify all clients of the same scope (room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { if (rcl != currentClient) { rcl.setMicMuted(true); this.clientListManager.updateClientByStreamId(rcl.getStreamid(), rcl); } log.debug("Send Flag to Client: " + rcl.getUsername()); if (conn instanceof IServiceCapableConnection) { ((IServiceCapableConnection) conn).invoke("receiveExclusiveAudioFlag", new Object[] { currentClient }, this); log.debug("sending receiveExclusiveAudioFlag to " + conn); } } } } } } catch (Exception err) { log.error("[giveExclusiveAudio]", err); } return -1L; } public synchronized Long switchMicMuted(String publicSID, boolean mute) { try { log.debug("*..*switchMicMuted publicSID: " + publicSID); RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return -1L; } currentClient.setMicMuted(mute); this.clientListManager.updateClientByStreamId(currentClient.getStreamid(), currentClient); HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>(); newMessage.put(0, "updateMuteStatus"); newMessage.put(1, currentClient); this.sendMessageWithClient(newMessage); } catch (Exception err) { log.error("[switchMicMuted]", err); } return 0L; } public synchronized Boolean getMicMutedByPublicSID(String publicSID) { try { RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { return true; } //Put the mod-flag to true for this client Boolean muted = currentClient.getMicMuted(); if (null == muted) { muted = true; } return muted; } catch (Exception err) { log.error("[getMicMutedByPublicSID]", err); } return true; } /** * Invoked by a User whenever he want to become moderator this is needed, * cause if the room has no moderator yet there is no-one he can ask to get * the moderation, in case its a Non-Moderated Room he should then get the * Moderation without any confirmation needed * * @return Long 1 => means get Moderation, 2 => ask Moderator for * Moderation, 3 => wait for Moderator */ public synchronized Long applyForModeration(String publicSID) { try { RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); List<RoomClient> currentModList = this.clientListManager .getCurrentModeratorByRoom(currentClient.getRoom_id()); if (currentModList.size() > 0) { return 2L; } else { // No moderator in this room at the moment Rooms room = roommanagement.getRoomById(currentClient.getRoom_id()); if (room.getIsModeratedRoom()) { return 3L; } else { return 1L; } } } catch (Exception err) { log.error("[applyForModeration]", err); } return -1L; } /** * there will be set an attribute called "broadCastCounter" this is the name * this user will publish his stream * * @return long broadCastId */ public synchronized long getBroadCastId() { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setBroadCastID(broadCastCounter++); this.clientListManager.updateClientByStreamId(streamid, currentClient); return currentClient.getBroadCastID(); } catch (Exception err) { log.error("[getBroadCastId]", err); } return -1; } /** * this must be set _after_ the Video/Audio-Settings have been chosen (see * editrecordstream.lzx) but _before_ anything else happens, it cannot be * applied _after_ the stream has started! avsettings can be: av - video and * audio a - audio only v - video only n - no a/v only static image * furthermore * * @param avsetting * @param newMessage * @return */ public synchronized RoomClient setUserAVSettings(String avsettings, Object newMessage, Integer vWidth, Integer vHeight, long room_id, String publicSID, Integer interviewPodId) { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setAvsettings(avsettings); currentClient.setRoom_id(room_id); currentClient.setPublicSID(publicSID); currentClient.setIsAVClient(true); currentClient.setVWidth(vWidth); currentClient.setVHeight(vHeight); currentClient.setInterviewPodId(interviewPodId); // Long room_id = currentClient.getRoom_id(); this.clientListManager.updateAVClientByStreamId(streamid, currentClient); HashMap<String, Object> hsm = new HashMap<String, Object>(); hsm.put("client", currentClient); hsm.put("message", newMessage); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this); } } } } } return currentClient; } catch (Exception err) { log.error("[setUserAVSettings]", err); } return null; } /* * checks if the user is allowed to apply for Moderation */ public synchronized Boolean checkRoomValues(Long room_id) { try { // appointed meeting or moderated Room? Rooms room = roommanagement.getRoomById(room_id); // not really - default logic if (room.getAppointment() == null || room.getAppointment() == false) { if (room.getIsModeratedRoom()) { // if this is a Moderated Room then the Room can be only // locked off by the Moderator Bit List<RoomClient> clientModeratorListRoom = this.clientListManager .getCurrentModeratorByRoom(room_id); // If there is no Moderator yet and we are asking for it // then deny it // cause at this moment, the user should wait untill a // Moderator enters the Room if (clientModeratorListRoom.size() == 0) { return false; } else { return true; } } else { return true; } } else { // FIXME: TODO: For Rooms that are created as Appointment we // have to check that too // but I don't know yet the Logic behind it - swagner 19.06.2009 return true; } } catch (Exception err) { log.error("[checkRoomValues]", err); } return false; } /** * This function is called once a User enters a Room * * It contains several different mechanism depending on what roomtype and * what options are available for the room to find out if the current user * will be a moderator of that room or not<br/> * <br/> * Some rules:<br/> * <ul> * <li>If it is a room that was created through the calendar, the user that * organized the room will be moderator, the param Boolean becomeModerator * will be ignored then</li> * <li>In regular rooms you can use the param Boolean becomeModerator to set * any user to become a moderator of the room</li> * </ul> * <br/> * If a new moderator is detected a Push Call to all current users of the * room is invoked "setNewModeratorByList" to notify them of the new * moderator<br/> * <br/> * And the end of the mechanism a push call with the new client-object * and all the informations about the new user is send to every user of the * current conference room<br/> * <br/> * @param room_id * @param colorObj * @return */ public synchronized RoomStatus setRoomValues(Long room_id, Boolean becomeModerator, Boolean isSuperModerator, Long organization_id, String colorObj) { try { // Return Object RoomStatus roomStatus = new RoomStatus(); IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setRoom_id(room_id); currentClient.setIsAVClient(false); currentClient.setRoomEnter(new Date()); currentClient.setOrganization_id(organization_id); currentClient.setUsercolor(colorObj); // Inject externalUserId if nothing is set yet if (currentClient.getExternalUserId() == null) { Users us = usersDao.getUser(currentClient.getUser_id()); if (us != null) { currentClient.setExternalUserId(us.getExternalUserId()); currentClient.setExternalUserType(us.getExternalUserType()); } } // This can be set without checking for Moderation Flag currentClient.setIsSuperModerator(isSuperModerator); this.clientListManager.updateClientByStreamId(streamid, currentClient); Rooms room = roommanagement.getRoomById(room_id); if (room.getShowMicrophoneStatus()) { currentClient.setCanGiveAudio(true); } // Log the User conferenceLogDao.addConferenceLog("roomEnter", currentClient.getUser_id(), streamid, room_id, currentClient.getUserip(), "", currentClient.getExternalUserId(), currentClient.getExternalUserType(), currentClient.getMail(), currentClient.getFirstname(), currentClient.getLastname()); log.debug("##### setRoomValues : " + currentClient); // Check for Moderation LogicalRoom ENTER HashMap<String, RoomClient> clientListRoom = this.clientListManager.getRoomClients(room_id); // appointed meeting or moderated Room? => Check Max Users first if (room.getNumberOfPartizipants() != null && clientListRoom.size() > room.getNumberOfPartizipants()) { roomStatus.setRoomFull(true); return roomStatus; } // default logic for non regular rooms if (room.getAppointment() == null || room.getAppointment() == false) { if (room.getIsModeratedRoom()) { // if this is a Moderated Room then the Room can be only // locked off by the Moderator Bit // List<RoomClient> clientModeratorListRoom = // this.clientListManager.getCurrentModeratorByRoom(room_id); // If there is no Moderator yet we have to check if the // current User has the Bit set to true to // become one, otherwise he won't get Moderation and has to // wait if (becomeModerator) { currentClient.setIsMod(true); // There is a need to send an extra Event here, cause at // this moment there could be // already somebody in the Room waiting // Update the Client List this.clientListManager.updateClientByStreamId(streamid, currentClient); List<RoomClient> modRoomList = this.clientListManager .getCurrentModeratorByRoom(currentClient.getRoom_id()); //Sync message to everybody syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false); } else { // The current User is not a Teacher/Admin or whatever // Role that should get the // Moderation currentClient.setIsMod(false); } } else { // If this is a normal Room Moderator rules : first come, // first draw ;-) log.debug("setRoomValues : Room" + room_id + " not appointed! Moderator rules : first come, first draw ;-)"); if (clientListRoom.size() == 1) { log.debug("Room is empty so set this user to be moderation role"); currentClient.setIsMod(true); } else { log.debug("Room is already somebody so set this user not to be moderation role"); if (becomeModerator) { currentClient.setIsMod(true); // Update the Client List this.clientListManager.updateClientByStreamId(streamid, currentClient); List<RoomClient> modRoomList = this.clientListManager .getCurrentModeratorByRoom(currentClient.getRoom_id()); // There is a need to send an extra Event here, // cause at this moment there could be // already somebody in the Room waiting -swagner check this comment, 20.01.2012 //Sync message to everybody syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false); } else { // The current User is not a Teacher/Admin or // whatever Role that should get the Moderation currentClient.setIsMod(false); } } } // Update the Client List this.clientListManager.updateClientByStreamId(streamid, currentClient); } else { // If this is an Appointment then the Moderator will be set to // the Invitor Appointment ment = appointmentLogic.getAppointmentByRoom(room_id); List<MeetingMember> members = meetingMemberDao .getMeetingMemberByAppointmentId(ment.getAppointmentId()); Long userIdInRoomClient = currentClient.getUser_id(); boolean found = false; boolean moderator_set = false; // Check if current user is set to moderator for (int i = 0; i < members.size(); i++) { MeetingMember member = members.get(i); // only persistent users can schedule a meeting // user-id is only set for registered users if (member.getUserid() != null) { log.debug("checking user " + member.getFirstname() + " for moderator role - ID : " + member.getUserid().getUser_id()); if (member.getUserid().getUser_id().equals(userIdInRoomClient)) { found = true; if (member.getInvitor()) { log.debug("User " + userIdInRoomClient + " is moderator due to flag in MeetingMember record"); currentClient.setIsMod(true); // Update the Client List this.clientListManager.updateClientByStreamId(streamid, currentClient); List<RoomClient> modRoomList = this.clientListManager .getCurrentModeratorByRoom(currentClient.getRoom_id()); // There is a need to send an extra Event here, cause at this moment // there could be already somebody in the Room waiting //Sync message to everybody syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false); moderator_set = true; this.clientListManager.updateClientByStreamId(streamid, currentClient); break; } else { log.debug("User " + userIdInRoomClient + " is NOT moderator due to flag in MeetingMember record"); currentClient.setIsMod(false); this.clientListManager.updateClientByStreamId(streamid, currentClient); break; } } else { if (member.getInvitor()) moderator_set = true; } } else { if (member.getInvitor()) moderator_set = true; } } if (!found) { log.debug("User " + userIdInRoomClient + " could not be found as MeetingMember -> definitely no moderator"); currentClient.setIsMod(false); this.clientListManager.updateClientByStreamId(streamid, currentClient); } else { // if current user is part of the member list, but moderator // couldn't be retrieved : first come, first draw! if (clientListRoom.size() == 1 && moderator_set == false) { log.debug(""); currentClient.setIsMod(true); // Update the Client List this.clientListManager.updateClientByStreamId(streamid, currentClient); List<RoomClient> modRoomList = this.clientListManager .getCurrentModeratorByRoom(currentClient.getRoom_id()); // There is a need to send an extra Event here, cause at // this moment there could be // already somebody in the Room waiting //Sync message to everybody syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false); this.clientListManager.updateClientByStreamId(streamid, currentClient); } } } //Sync message to everybody syncMessageToCurrentScope("addNewUser", currentClient, false); //Status object for Shared Browsing BrowserStatus browserStatus = (BrowserStatus) current.getScope().getAttribute("browserStatus"); if (browserStatus == null) { browserStatus = new BrowserStatus(); } // RoomStatus roomStatus = new RoomStatus(); // FIXME: Rework Client Object to DTOs roomStatus.setClientMap(clientListRoom); roomStatus.setBrowserStatus(browserStatus); return roomStatus; } catch (Exception err) { log.error("[setRoomValues]", err); } return null; } /** * This method is invoked when the user has disconnected and reconnects to * the Gateway with the new scope * * @param SID * @param userId * @param username * @param firstname * @param lastname * @param picture_uri * @return */ public synchronized RoomClient setUsernameReconnect(String SID, Long userId, String username, String firstname, String lastname, String picture_uri) { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setUsername(username); currentClient.setUser_id(userId); currentClient.setPicture_uri(picture_uri); currentClient.setUserObject(userId, username, firstname, lastname); // Update Session Data sessionManagement.updateUserWithoutSession(SID, userId); Users user = userManagement.getUserById(userId); if (user != null) { currentClient.setExternalUserId(user.getExternalUserId()); currentClient.setExternalUserType(user.getExternalUserType()); } // only fill this value from User-Record // cause invited users have non // you cannot set the firstname,lastname from the UserRecord Users us = usersDao.getUser(userId); if (us != null && us.getPictureuri() != null) { // set Picture-URI currentClient.setPicture_uri(us.getPictureuri()); } this.clientListManager.updateClientByStreamId(streamid, currentClient); return currentClient; } catch (Exception err) { log.error("[setUsername]", err); } return null; } /** * this is set initial directly after login/loading language * * @param userId * @param username * @param firstname * @param lastname * @param orgdomain * @return */ public synchronized RoomClient setUsernameAndSession(String SID, Long userId, String username, String firstname, String lastname) { try { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setUsername(username); currentClient.setUser_id(userId); currentClient.setUserObject(userId, username, firstname, lastname); // Update Session Data log.debug("UDPATE SESSION " + SID + ", " + userId); sessionManagement.updateUserWithoutSession(SID, userId); Users user = userManagement.getUserById(userId); if (user != null) { currentClient.setExternalUserId(user.getExternalUserId()); currentClient.setExternalUserType(user.getExternalUserType()); } // only fill this value from User-Record // cause invited users have non // you cannot set the firstname,lastname from the UserRecord Users us = usersDao.getUser(userId); if (us != null && us.getPictureuri() != null) { // set Picture-URI currentClient.setPicture_uri(us.getPictureuri()); } this.clientListManager.updateClientByStreamId(streamid, currentClient); return currentClient; } catch (Exception err) { log.error("[setUsername]", err); } return null; } /** * used by the Screen-Sharing Servlet to trigger events * * @param room_id * @param message * @return */ public synchronized HashMap<String, RoomClient> sendMessageByRoomAndDomain(Long room_id, Object message) { HashMap<String, RoomClient> roomClientList = new HashMap<String, RoomClient>(); try { log.debug("sendMessageByRoomAndDomain " + room_id); IScope globalScope = getContext().getGlobalScope(); IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey); log.debug("webAppKeyScope " + webAppKeyScope); IScope scopeHibernate = webAppKeyScope.getScope(room_id.toString()); // IScope scopeHibernate = webAppKeyScope.getScope("hibernate"); if (scopeHibernate != null) { Collection<Set<IConnection>> conCollection = webAppKeyScope.getScope(room_id.toString()) .getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { if (conn instanceof IServiceCapableConnection) { // RoomClient rcl = // this.clientListManager.getClientByStreamId(conn.getClient().getId()); ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this); // log.debug("sending newMessageByRoomAndDomain to " // + conn); } } } } } } else { log.debug("sendMessageByRoomAndDomain servlet not yet started - roomID : '" + room_id + "'"); } } catch (Exception err) { log.error("[getClientListBYRoomAndDomain]", err); } return roomClientList; } public synchronized List<RoomClient> getCurrentModeratorList() { try { log.debug("*..*getCurrentModerator id: "); IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); Long room_id = currentClient.getRoom_id(); // log.debug("Who is this moderator? "+currentMod); return this.clientListManager.getCurrentModeratorByRoom(room_id); } catch (Exception err) { log.error("[getCurrentModerator]", err); } return null; } /** * This Function is triggered from the Whiteboard * * @param whiteboardObj * @return */ @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized void sendVars(ArrayList whiteboardObjParam) { // try { // In previous version this has been always a Map, now its a List // so I re-wrapp that class to be a Map again. // swagner 13.02.2009 // log.debug("*..*sendVars1: " + whiteboardObjParam); // log.debug("*..*sendVars2: " + whiteboardObjParam.getClass()); // log.debug("*..*sendVars3: " + // whiteboardObjParam.getClass().getName()); Map whiteboardObj = new HashMap(); int i = 0; for (Iterator iter = whiteboardObjParam.iterator(); iter.hasNext();) { Object obj = iter.next(); // log.debug("obj"+obj); whiteboardObj.put(i, obj); i++; } // Map whiteboardObj = (Map) whiteboardObjParam; // Check if this User is the Mod: IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); if (currentClient == null) { return; } Long room_id = currentClient.getRoom_id(); String action = whiteboardObj.get(2).toString(); // log.debug("***** sendVars: " + actionObject.get(0)); if (action != null && action.equals("whiteboardObj")) { // Update Whiteboard Object List actionObject = (List) whiteboardObj.get(3); WhiteboardManagement.getInstance().updateWhiteboardObject(room_id, actionObject); } else if (action != null && action.equals("moveMap")) { // Update Whiteboard Object List actionObject = (List) whiteboardObj.get(3); WhiteboardManagement.getInstance().updateWhiteboardObjectPos(room_id, actionObject); } else { // Store event in list WhiteboardManagement.getInstance().addWhiteBoardObject(room_id, whiteboardObj); } boolean showDrawStatus = getWhiteboardDrawStatus(); // Notify all Clients of that Scope (Room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { if (conn.getClient().getId().equals(current.getClient().getId())) { continue; } RoomClient rcl = this.clientListManager .getSyncClientByStreamId(conn.getClient().getId()); if (rcl == null) { continue; } if (!currentClient.getStreamid().equals(rcl.getStreamid())) { ((IServiceCapableConnection) conn).invoke("sendVarsToWhiteboard", new Object[] { (showDrawStatus ? currentClient : null), whiteboardObj }, this); } } } } } } catch (Exception err) { log.error("[sendVars]", err); } } /** * This Function is triggered from the Whiteboard * * @param whiteboardObj * @return */ @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized void sendVarsByWhiteboardId(ArrayList whiteboardObjParam, Long whiteboardId) { // try { Map whiteboardObj = new HashMap(); int i = 0; for (Iterator iter = whiteboardObjParam.iterator(); iter.hasNext();) { Object obj = iter.next(); // log.debug("obj"+obj); whiteboardObj.put(i, obj); i++; } // Check if this User is the Mod: IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); if (currentClient == null) { return; } Long room_id = currentClient.getRoom_id(); // log.debug("***** sendVars: " + whiteboardObj); // Store event in list String action = whiteboardObj.get(2).toString(); if (action.equals("deleteMindMapNodes")) { // Simulate Single Delete Events for z-Index List actionObject = (List) whiteboardObj.get(3); List<List> itemObjects = (List) actionObject.get(3); Map whiteboardTempObj = new HashMap(); whiteboardTempObj.put(2, "delete"); for (List itemObject : itemObjects) { List<Object> tempActionObject = new LinkedList<Object>(); tempActionObject.add("mindmapnode"); tempActionObject.add(itemObject.get(0)); // z-Index -8 tempActionObject.add(null); // simulate -7 tempActionObject.add(null); // simulate -6 tempActionObject.add(null); // simulate -5 tempActionObject.add(null); // simulate -4 tempActionObject.add(null); // simulate -3 tempActionObject.add(null); // simulate -2 tempActionObject.add(itemObject.get(1)); // Object-Name -1 whiteboardTempObj.put(3, tempActionObject); WhiteboardManagement.getInstance().addWhiteBoardObjectById(room_id, whiteboardTempObj, whiteboardId); } } else { WhiteboardManagement.getInstance().addWhiteBoardObjectById(room_id, whiteboardObj, whiteboardId); } // This is no longer necessary // boolean ismod = currentClient.getIsMod(); // log.debug("*..*ismod: " + ismod); // if (ismod) { Map<String, Object> sendObject = new HashMap<String, Object>(); sendObject.put("id", whiteboardId); sendObject.put("param", whiteboardObjParam); boolean showDrawStatus = getWhiteboardDrawStatus(); // Notify all Clients of that Scope (Room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { if (conn.getClient().getId().equals(current.getClient().getId())) { continue; } RoomClient rcl = this.clientListManager .getSyncClientByStreamId(conn.getClient().getId()); if (rcl == null) { continue; } if (!currentClient.getStreamid().equals(rcl.getStreamid())) { ((IServiceCapableConnection) conn).invoke("sendVarsToWhiteboardById", new Object[] { showDrawStatus ? currentClient : null, sendObject }, this); } } } } } // return numberOfUsers; // } else { // // log.debug("*..*you are not allowed to send: "+ismod); // return -1; // } } catch (Exception err) { log.error("[sendVarsByWhiteboardId]", err); } } public synchronized int sendVarsModeratorGeneral(Object vars) { log.debug("*..*sendVars: " + vars); try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); // Long room_id = currentClient.getRoom_id(); log.debug("***** id: " + currentClient.getStreamid()); boolean ismod = currentClient.getIsMod(); if (ismod) { log.debug("CurrentScope :" + current.getScope().getName()); // Send to all Clients of the same Scope Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { RoomClient rcl = this.clientListManager .getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { // log.debug("*..*idremote: " + // rcl.getStreamid()); // log.debug("*..*my idstreamid: " + // currentClient.getStreamid()); if (!currentClient.getStreamid().equals(rcl.getStreamid())) { ((IServiceCapableConnection) conn).invoke("sendVarsToModeratorGeneral", new Object[] { vars }, this); // log.debug("sending sendVarsToModeratorGeneral to " // + conn); } } } } } } return 1; } else { // log.debug("*..*you are not allowed to send: "+ismod); return -1; } } catch (Exception err) { log.error("[sendVarsModeratorGeneral]", err); } return -1; } public synchronized int sendMessage(Object newMessage) { try { syncMessageToCurrentScope("sendVarsToMessage", newMessage, false); } catch (Exception err) { log.error("[sendMessage]", err); } return 1; } public synchronized int sendMessageAll(Object newMessage) { try { syncMessageToCurrentScope("sendVarsToMessage", newMessage, true); } catch (Exception err) { log.error("[sendMessage]", err); } return 1; } /** * send status for shared browsing to all members except self * @param newMessage * @return */ @SuppressWarnings({ "rawtypes" }) public synchronized int sendBrowserMessageToMembers(Object newMessage) { try { IConnection current = Red5.getConnectionLocal(); List newMessageList = (List) newMessage; String action = newMessageList.get(0).toString(); BrowserStatus browserStatus = (BrowserStatus) current.getScope().getAttribute("browserStatus"); if (browserStatus == null) { browserStatus = new BrowserStatus(); } if (action.equals("initBrowser") || action.equals("newBrowserURL")) { browserStatus.setBrowserInited(true); browserStatus.setCurrentURL(newMessageList.get(1).toString()); } else if (action.equals("closeBrowserURL")) { browserStatus.setBrowserInited(false); } current.getScope().setAttribute("browserStatus", browserStatus); syncMessageToCurrentScope("sendVarsToMessage", newMessage, false); } catch (Exception err) { log.error("[sendMessage]", err); } return 1; } /** * wrapper method * @param newMessage * @return */ public synchronized int sendMessageToMembers(Object newMessage) { try { //Sync to all users of current scope syncMessageToCurrentScope("sendVarsToMessage", newMessage, false); } catch (Exception err) { log.error("[sendMessage]", err); } return 1; } /** * General sync mechanism for all messages that are send from within the * scope of the current client, but: * <ul> * <li>optionally do not send to self (see param: sendSelf)</li> * <li>do not send to clients that are screen sharing clients</li> * <li>do not send to clients that are audio/video clients (or potentially ones)</li> * <li>do not send to connections where no RoomClient is registered</li> * </ul> * * @param remoteMethodName * @param newMessage * @param sendSelf * @return */ public synchronized int syncMessageToCurrentScope(String remoteMethodName, Object newMessage, boolean sendSelf) { try { IConnection current = Red5.getConnectionLocal(); // Send to all Clients of that Scope(Room) Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // RoomClient can be null if there are network problems continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // screen sharing clients do not receive events continue; } else if (rcl.getIsAVClient()) { // AVClients or potential AVClients do not receive events continue; } else if (current.getClient().getId().equals(conn.getClient().getId()) && !sendSelf) { //Do not send back to self continue; } ((IServiceCapableConnection) conn).invoke(remoteMethodName, new Object[] { newMessage }, this); } } } } } catch (Exception err) { log.error("[syncMessageToCurrentScope]", err); } return 1; } /** * wrapper method * @param newMessage * @return */ public synchronized int sendMessageWithClient(Object newMessage) { try { sendMessageWithClientWithSyncObject(newMessage, true); } catch (Exception err) { log.error("[sendMessageWithClient] ", err); return -1; } return 1; } /** * wrapper method * @param newMessage * @param sync * @return */ public synchronized int sendMessageWithClientWithSyncObject(Object newMessage, boolean sync) { try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); HashMap<String, Object> hsm = new HashMap<String, Object>(); hsm.put("client", currentClient); hsm.put("message", newMessage); //Sync to all users of current scope syncMessageToCurrentScope("sendVarsToMessageWithClient", hsm, sync); } catch (Exception err) { log.error("[sendMessageWithClient] ", err); return -1; } return 1; } /** * Function is used to send the kick Trigger at the moment, * it sends a general message to a specific clientId * * @param newMessage * @param clientId * @return */ public synchronized int sendMessageById(Object newMessage, String clientId, IScope scope) { try { log.debug("### sendMessageById ###" + clientId); HashMap<String, Object> hsm = new HashMap<String, Object>(); hsm.put("message", newMessage); // broadcast Message to specific user with id inside the same Scope Collection<Set<IConnection>> conCollection = scope.getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { if (conn instanceof IServiceCapableConnection) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { // log.debug("### sendMessageById 1 ###"+clientId); // log.debug("### sendMessageById 2 ###"+conn.getClient().getId()); if (conn.getClient().getId().equals(clientId)) { ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this); // log.debug("sendingsendVarsToMessageWithClient ByID to " // + conn); } } } } } } } catch (Exception err) { log.error("[sendMessageWithClient] ", err); return -1; } return 1; } /** * Sends a message to a user in the same room by its clientId * * @param newMessage * @param clientId * @return */ public synchronized int sendMessageWithClientById(Object newMessage, String clientId) { try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); log.debug("### sendMessageWithClientById ###" + clientId); HashMap<String, Object> hsm = new HashMap<String, Object>(); hsm.put("client", currentClient); hsm.put("message", newMessage); // broadcast Message to specific user with id inside the same Scope Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { if (conn instanceof IServiceCapableConnection) { // log.debug("### sendMessageWithClientById 1 ###"+clientId); // log.debug("### sendMessageWithClientById 2 ###"+conn.getClient().getId()); if (conn.getClient().getId().equals(clientId)) { ((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient", new Object[] { hsm }, this); // log.debug("sendingsendVarsToMessageWithClient ByID to " // + conn); } } } } } } } catch (Exception err) { log.error("[sendMessageWithClient] ", err); return -1; } return 1; } public synchronized void sendMessageWithClientByPublicSID(Object message, String publicSID) { try { // ApplicationContext appCtx = getContext().getApplicationContext(); IScope globalScope = getContext().getGlobalScope(); IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey); // log.debug("webAppKeyScope "+webAppKeyScope); // Get Room Id to send it to the correct Scope RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { throw new Exception("Could not Find RoomClient on List publicSID: " + publicSID); } // default Scope Name String scopeName = "hibernate"; if (currentClient.getRoom_id() != null) { scopeName = currentClient.getRoom_id().toString(); } IScope scopeHibernate = webAppKeyScope.getScope(scopeName); // log.debug("scopeHibernate "+scopeHibernate); if (scopeHibernate != null) { // Notify the clients of the same scope (room) with user_id Collection<Set<IConnection>> conCollection = webAppKeyScope.getScope(scopeName).getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl != null) { if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { // log.debug("rcl "+rcl+" rcl.getUser_id(): "+rcl.getPublicSID()+" publicSID: "+publicSID+ // " IS EQUAL? "+rcl.getPublicSID().equals(publicSID)); if (rcl.getPublicSID().equals(publicSID)) { // log.debug("IS EQUAL "); ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this); log.debug("newMessageByRoomAndDomain RPC:newMessageByRoomAndDomain" + message); } } } } } } } else { // Scope not yet started } } catch (Exception err) { log.error("[sendMessageWithClient] ", err); err.printStackTrace(); } } public synchronized void sendMessageWithClientByPublicSIDOrUser(Object message, String publicSID, Long user_id) { try { // ApplicationContext appCtx = getContext().getApplicationContext(); IScope globalScope = getContext().getGlobalScope(); IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey); // log.debug("webAppKeyScope "+webAppKeyScope); // Get Room Id to send it to the correct Scope RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false); if (currentClient == null) { currentClient = this.clientListManager.getClientByUserId(user_id); } Collection<Set<IConnection>> conCollection = null; if (currentClient == null) { // Must be from a previous session, search for user in current // scope IConnection current = Red5.getConnectionLocal(); // Notify all Clients of that Scope (Room) conCollection = current.getScope().getConnections(); } else { // default Scope Name String scopeName = "hibernate"; if (currentClient.getRoom_id() != null) { scopeName = currentClient.getRoom_id().toString(); } IScope scopeHibernate = webAppKeyScope.getScope(scopeName); if (scopeHibernate != null) { conCollection = webAppKeyScope.getScope(scopeName).getConnections(); } } // log.debug("scopeHibernate "+scopeHibernate); // Notify the clients of the same scope (room) with user_id for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl != null) { if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { // log.debug("rcl "+rcl+" rcl.getUser_id(): "+rcl.getPublicSID()+" publicSID: "+publicSID+ // " IS EQUAL? "+rcl.getPublicSID().equals(publicSID)); if (rcl.getPublicSID().equals(publicSID)) { // log.debug("IS EQUAL "); ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this); log.debug("sendMessageWithClientByPublicSID RPC:newMessageByRoomAndDomain" + message); } else if (user_id != 0 && rcl.getUser_id() != null && rcl.getUser_id().equals(user_id)) { ((IServiceCapableConnection) conn).invoke("newMessageByRoomAndDomain", new Object[] { message }, this); log.debug("sendMessageWithClientByPublicSID RPC:newMessageByRoomAndDomain" + message); } } } } } } } catch (Exception err) { log.error("[sendMessageWithClient] ", err); err.printStackTrace(); } } public synchronized Boolean getInterviewRecordingStatus() { try { IConnection current = Red5.getConnectionLocal(); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl.getIsRecording() != null && rcl.getIsRecording()) { return true; } } } } return false; } catch (Exception err) { log.error("[getInterviewRecordingStatus]", err); } return null; } public synchronized Boolean startInterviewRecording() { try { IConnection current = Red5.getConnectionLocal(); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl.getIsRecording() != null && rcl.getIsRecording()) { return false; } } } } RoomClient current_rcl = this.clientListManager.getClientByStreamId(current.getClient().getId()); // Also set the Recording Flag to Record all Participants that enter // later current_rcl.setIsRecording(true); this.clientListManager.updateClientByStreamId(current.getClient().getId(), current_rcl); Map<String, String> interviewStatus = new HashMap<String, String>(); interviewStatus.put("action", "start"); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { continue; } else if (rcl.getIsAVClient()) { continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { continue; } ((IServiceCapableConnection) conn).invoke("interviewStatus", new Object[] { interviewStatus }, this); log.debug("-- interviewStatus" + interviewStatus); } } } String recordingName = "Interview " + CalendarPatterns.getDateWithTimeByMiliSeconds(new Date()); this.flvRecorderService.recordMeetingStream(recordingName, "", true); return true; } catch (Exception err) { log.debug("[startInterviewRecording]", err); } return null; } @SuppressWarnings({ "rawtypes" }) public synchronized Boolean sendRemoteCursorEvent(String streamid, Map messageObj) { try { IConnection current = Red5.getConnectionLocal(); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { if (rcl.getStreamid() != null && rcl.getStreamid().equals(streamid)) { ((IServiceCapableConnection) conn).invoke("sendRemoteCursorEvent", new Object[] { messageObj }, this); log.debug("sendRemoteCursorEvent messageObj" + messageObj); } } } } } } catch (Exception err) { log.debug("[sendRemoteCursorEvent]", err); } return null; } //FIXME: legacy code, needs to be removed public boolean checkSharerSession() { return true; } /** * Stop the recording of the streams and send event to connected users of scope * * @return */ public synchronized Boolean stopInterviewRecording() { try { IConnection current = Red5.getConnectionLocal(); boolean found = false; Long flvRecordingId = null; Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl.getIsRecording() != null && rcl.getIsRecording()) { rcl.setIsRecording(false); flvRecordingId = rcl.getFlvRecordingId(); rcl.setFlvRecordingId(null); // Reset the Recording Flag to Record all // Participants that enter later this.clientListManager.updateClientByStreamId(conn.getClient().getId(), rcl); found = true; } } } } if (!found) { return false; } RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); this.flvRecorderService.stopRecordAndSave(scope, currentClient, flvRecordingId); Map<String, String> interviewStatus = new HashMap<String, String>(); interviewStatus.put("action", "stop"); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { ((IServiceCapableConnection) conn).invoke("interviewStatus", new Object[] { interviewStatus }, this); log.debug("sendMessageWithClientByPublicSID interviewStatus" + interviewStatus); } } } return true; } catch (Exception err) { log.debug("[startInterviewRecording]", err); } return null; } /** * Get all ClientList Objects of that room and domain Used in * lz.applyForModeration.lzx * * @return */ public synchronized HashMap<String, RoomClient> getClientListScope() { HashMap<String, RoomClient> roomClientList = new HashMap<String, RoomClient>(); try { IConnection current = Red5.getConnectionLocal(); RoomClient currentClient = this.clientListManager.getClientByStreamId(current.getClient().getId()); return this.clientListManager.getClientListByRoom(currentClient.getRoom_id()); } catch (Exception err) { log.debug("[getClientListScope]", err); } return roomClientList; } private boolean getWhiteboardDrawStatus() { if (ScopeApplicationAdapter.whiteboardDrawStatus == null) { String drawStatus = cfgManagement.getConfValue("show.whiteboard.draw.status", String.class, "0"); ScopeApplicationAdapter.whiteboardDrawStatus = "1".equals(drawStatus); } return ScopeApplicationAdapter.whiteboardDrawStatus; } public String getCryptKey() { try { if (ScopeApplicationAdapter.configKeyCryptClassName == null) { Configuration conf = cfgManagement.getConfKey(3, "crypt_ClassName"); if (conf != null) { ScopeApplicationAdapter.configKeyCryptClassName = conf.getConf_value(); } } return ScopeApplicationAdapter.configKeyCryptClassName; } catch (Exception err) { log.error("[getCryptKey]", err); } return null; } public String getExclusiveAudioKeyCode() { Configuration conf = cfgManagement.getConfKey(3, "exclusive.audio.keycode"); if (null != conf) { return conf.getConf_value(); } else { return null; } } public synchronized IScope getRoomScope(String room) { try { IScope globalScope = getContext().getGlobalScope(); IScope webAppKeyScope = globalScope.getScope(OpenmeetingsVariables.webAppRootKey); String scopeName = "hibernate"; // If set then its a NON default Scope if (room.length() != 0) { scopeName = room; } IScope scopeHibernate = webAppKeyScope.getScope(scopeName); return scopeHibernate; } catch (Exception err) { log.error("[getRoomScope]", err); } return null; } /* * SIP transport methods */ public synchronized void updateSipTransport() { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); log.debug("getSipConferenceMembersNumber: " + roommanagement.getSipConferenceMembersNumber(currentClient.getRoom_id())); String newNumber = "(" + Integer.toString(roommanagement.getSipConferenceMembersNumber(currentClient.getRoom_id()) - 1) + ")"; if (!newNumber.equals(currentClient.getLastname())) { currentClient.setLastname(newNumber); this.clientListManager.updateClientByStreamId(streamid, currentClient); log.debug("updateSipTransport: {}, {}, {}, {}", new Object[] { currentClient.getPublicSID(), currentClient.getRoom_id(), currentClient.getFirstname(), currentClient.getLastname() }); sendMessageWithClient( new String[] { "personal", currentClient.getFirstname(), currentClient.getLastname() }); } } /** * Perform call to specified phone number and join to conference * @param number to call */ public synchronized void joinToConfCall(String number) { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); Rooms rooms = roommanagement.getRoomById(currentClient.getRoom_id()); log.debug("asterisk -rx \"originate Local/" + number + "@rooms extension " + rooms.getSipNumber() + "@rooms\""); try { Runtime.getRuntime().exec(new String[] { "asterisk", "-rx", "originate Local/" + number + "@rooms extension " + rooms.getSipNumber() + "@rooms" }); } catch (IOException e) { log.error("Executing asterisk originate error: ", e); } } public synchronized String getSipNumber(Long room_id) { Rooms rooms = roommanagement.getRoomById(room_id); if (rooms != null) { log.debug("getSipNumber: room_id: {}, sipNumber: {}", new Object[] { room_id, rooms.getSipNumber() }); return rooms.getSipNumber(); } return null; } public synchronized void setSipTransport(Long room_id, String publicSID, String broadCastId) { IConnection current = Red5.getConnectionLocal(); String streamid = current.getClient().getId(); // Notify all clients of the same scope (room) RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid); currentClient.setRoom_id(room_id); currentClient.setRoomEnter(new Date()); currentClient.setFirstname("SIP Transport"); currentClient.setLastname( "(" + Integer.toString(roommanagement.getSipConferenceMembersNumber(room_id) - 1) + ")"); currentClient.setBroadCastID(Long.parseLong(broadCastId)); currentClient.setIsBroadcasting(true); currentClient.setPublicSID(publicSID); currentClient.setAvsettings("av"); currentClient.setVWidth(120); currentClient.setVHeight(90); this.clientListManager.updateClientByStreamId(streamid, currentClient); Collection<Set<IConnection>> conCollection = current.getScope().getConnections(); for (Set<IConnection> conset : conCollection) { for (IConnection conn : conset) { if (conn != null) { RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId()); if (rcl == null) { // continue; } else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) { // continue; } else { if (!streamid.equals(rcl.getStreamid())) { // It is not needed to send back // that event to the actuall // Moderator // as it will be already triggered // in the result of this Function // in the Client if (conn instanceof IServiceCapableConnection) { ((IServiceCapableConnection) conn).invoke("addNewUser", new Object[] { currentClient }, this); ((IServiceCapableConnection) conn).invoke("newStream", new Object[] { currentClient }, this); log.debug("sending setSipTransport to " + conn); } } } } } } } }