You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/03/10 10:19:06 UTC

svn commit: r1786321 - in /openmeetings/application: branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ branches/3.2.x/openmeeting...

Author: solomax
Date: Fri Mar 10 10:19:06 2017
New Revision: 1786321

URL: http://svn.apache.org/viewvc?rev=1786321&view=rev
Log:
[OPENMEETINGS-1598] disabled for AV devices seems to work

Modified:
    openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
    openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
    openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
    openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
    openmeetings/application/branches/3.2.x/openmeetings-flash/src/main/swf/video/editRecordStreamSWF10.lzx
    openmeetings/application/branches/3.2.x/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
    openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
    openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
    openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
    openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
    openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
    openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
    openmeetings/application/trunk/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
    openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
    openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java

Modified: openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java Fri Mar 10 10:19:06 2017
@@ -242,29 +242,6 @@ public class MainService implements IPen
 		return new Long(-1);
 	}
 
-	/**
-	 * clear this session id
-	 *
-	 * @param sid
-	 * @return string value if completed
-	 */
-	public Long logoutUser(String sid) {
-		try {
-			Sessiondata sd = sessionDao.check(sid);
-			IConnection current = Red5.getConnectionLocal();
-			Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
-			scopeApplicationAdapter.roomLeaveByScope(currentClient,current.getScope(), false);
-
-			currentClient.setUserObject(null, null, null, null);
-
-			return userManager.logout(sid, sd.getUserId());
-		} catch (Exception err) {
-			log.error("[logoutUser]",err);
-		}
-		return -1L;
-	}
-
 	public List<Configuration> getGeneralOptions() {
 		try {
 			return configurationDao.get("exclusive.audio.keycode", CONFIG_SIP_ENABLED, CONFIG_MAX_UPLOAD_SIZE_KEY, "mute.keycode", CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY);

Modified: openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java Fri Mar 10 10:19:06 2017
@@ -248,7 +248,7 @@ public class RecordingService implements
 	 *
 	 * @param conn
 	 */
-	public void stopRecordingShow(IConnection conn, String broadcastId, Long metaId) {
+	public void stopRecordingShow(IScope scope, String broadcastId, Long metaId) {
 		try {
 			if (metaId == null) {
 				// this should be fixed, can be useful for debugging, after all this is an error
@@ -256,10 +256,10 @@ public class RecordingService implements
 				log.error("recordingMetaDataId is null");
 			}
 
-			log.debug("** stopRecordingShow: " + conn);
-			log.debug("### Stop recording show for broadcastId: " + broadcastId + " || " + conn.getScope().getContextPath());
+			log.debug("** stopRecordingShow: " + scope);
+			log.debug("### Stop recording show for broadcastId: " + broadcastId + " || " + scope.getContextPath());
 
-			Object streamToClose = scopeApplicationAdapter.getBroadcastStream(conn.getScope(), broadcastId);
+			Object streamToClose = scopeApplicationAdapter.getBroadcastStream(scope, broadcastId);
 
 			StreamListener listenerAdapter = streamListeners.get(metaId);
 
@@ -327,14 +327,14 @@ public class RecordingService implements
 						if (rcl.isScreenClient()) {
 							if (rcl.getRecordingId() != null && rcl.isScreenPublishStarted()) {
 								// Stop FLV Recording
-								stopRecordingShow(conn, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
+								stopRecordingShow(scope, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
 
 								// Update Meta Data
 								metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
 							}
 						} else if (rcl.getAvsettings().equals("av") || rcl.getAvsettings().equals("a") || rcl.getAvsettings().equals("v")) {
 
-							stopRecordingShow(conn, String.valueOf(rcl.getBroadCastID()).toString(), rcl.getRecordingMetaDataId());
+							stopRecordingShow(scope, String.valueOf(rcl.getBroadCastID()).toString(), rcl.getRecordingMetaDataId());
 
 							// Update Meta Data
 							metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
@@ -397,7 +397,7 @@ public class RecordingService implements
 		return null;
 	}
 
-	public void stopRecordingShowForClient(IConnection conn, Client rcl) {
+	public void stopRecordingShowForClient(IScope scope, Client rcl) {
 		try {
 			// this cannot be handled here, as to stop a stream and to leave a
 			// room is not
@@ -414,7 +414,7 @@ public class RecordingService implements
 					// FIXME: Is there really a need to stop it manually if the
 					// user just
 					// stops the stream?
-					stopRecordingShow(conn, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
+					stopRecordingShow(scope, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
 
 					// Update Meta Data
 					metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
@@ -424,7 +424,7 @@ public class RecordingService implements
 
 				// FIXME: Is there really a need to stop it manually if the user
 				// just stops the stream?
-				stopRecordingShow(conn, String.valueOf(rcl.getBroadCastID()), rcl.getRecordingMetaDataId());
+				stopRecordingShow(scope, String.valueOf(rcl.getBroadCastID()), rcl.getRecordingMetaDataId());
 
 				// Update Meta Data
 				metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());

Modified: openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java Fri Mar 10 10:19:06 2017
@@ -146,7 +146,7 @@ public class UserService implements IUse
 					messageObj.put(0, "kick");
 					scopeApplicationAdapter.sendMessageById(messageObj, streamid, currentScope);
 
-					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 					return true;
 				} else {
@@ -199,7 +199,7 @@ public class UserService implements IUse
 				messageObj.put(0, "kick");
 
 				scopeApplicationAdapter.sendMessageById(messageObj, rcl.getStreamid(), currentScope);
-				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 				return true;
 			}

Modified: openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java Fri Mar 10 10:19:06 2017
@@ -443,7 +443,7 @@ public class ScopeApplicationAdapter ext
 					returnMap.put("alreadyPublished", true);
 				}
 
-				log.debug(String.format("screen x,y,width,height %s,%s,%s,%s", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight()));
+				log.debug("screen x,y,width,height {},{},{},{}", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight());
 
 				if (startStreaming) {
 					if (!alreadyStreaming) {
@@ -559,43 +559,27 @@ public class ScopeApplicationAdapter ext
 	@Override
 	public void roomLeave(IClient client, IScope room) {
 		try {
-			log.debug(String.format("roomLeave %s %s %s %s", client.getId(), room.getClients().size(), room.getContextPath(), room.getName()));
+			log.debug("[roomLeave] {} {} {} {}", client.getId(), room.getClients().size(), room.getContextPath(), room.getName());
 
-			Client currentClient = sessionManager.getClientByStreamId(client.getId(), null);
+			Client rcl = sessionManager.getClientByStreamId(client.getId(), null);
 
 			// The Room Client can be null if the Client left the room by using
 			// logicalRoomLeave
-			if (currentClient != null) {
+			if (rcl != null) {
 				log.debug("currentClient IS NOT NULL");
-				roomLeaveByScope(currentClient, room, true);
+				roomLeaveByScope(rcl, room);
 			}
 		} 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 void logicalRoomLeave() {
-		log.debug("logicalRoomLeave ");
-		try {
-			IConnection current = Red5.getConnectionLocal();
-			String streamid = current.getClient().getId();
-
-			log.debug(streamid + " is leaving");
-
-			Client currentClient = sessionManager.getClientByStreamId(streamid, null);
-
-			roomLeaveByScope(currentClient, current.getScope(), true);
-		} catch (Exception err) {
-			log.error("[logicalRoomLeave]", err);
+	public void roomLeaveByScope(String uid, Long roomId) {
+		Client rcl = sessionManager.getClientByPublicSID(uid, null);
+		IScope scope = getRoomScope("" + roomId);
+		log.debug("[roomLeaveByScope] {} {} {} {}", uid, roomId, rcl, scope);
+		if (rcl != null && scope != null) {
+			roomLeaveByScope(rcl, scope);
 		}
 	}
 
@@ -609,9 +593,9 @@ public class ScopeApplicationAdapter ext
 	 * @param client
 	 * @param scope
 	 */
-	public void roomLeaveByScope(Client client, IScope scope, boolean removeUserFromSessionList) {
+	public void roomLeaveByScope(Client client, IScope scope) {
 		try {
-			log.debug("currentClient " + client);
+			log.debug("[roomLeaveByScope] currentClient " + client);
 			Long roomId = client.getRoomId();
 
 			if (client.isScreenClient() && client.isStartStreaming()) {
@@ -642,59 +626,30 @@ public class ScopeApplicationAdapter ext
 					client.setIsRecording(true);
 				}
 			}
+			recordingService.stopRecordingShowForClient(scope, client);
 
 			// 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 " + scope);
 
-			if (scope != null && scope.getClientConnections() != null) {
-				// Notify Users of the current Scope
-				for (IConnection cons : scope.getClientConnections()) {
-					if (cons != null && cons instanceof IServiceCapableConnection) {
-						log.debug("sending roomDisconnect to {}  client id {}", cons, cons.getClient().getId());
-
-						Client rcl = sessionManager.getClientByStreamId(cons.getClient().getId(), null);
-
-						// Check if the Client does still exist on the list
-						if (rcl == null) {
-							log.debug("For this StreamId: " + cons.getClient().getId() + " There is no Client in the List anymore");
-							continue;
-						}
-
-						//Do not send back to sender, but actually all other clients should receive this message swagner 01.10.2009
-						if (!client.getStreamid().equals(rcl.getStreamid())) {
-							// add Notification if another user isrecording
-							log.debug("###########[roomLeaveByScope]");
-							if (rcl.getIsRecording()) {
-								log.debug("*** roomLeave Any Client is Recording - stop that");
-								recordingService.stopRecordingShowForClient(cons, client);
-							}
-
-							boolean isScreen = rcl.isScreenClient();
-							if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
-								//going to terminate screen sharing started by this client
-								((IServiceCapableConnection) cons).invoke("stopStream", new Object[] { },this);
-								continue;
-							} else if (isScreen) {
-								// screen sharing clients do not receive events
-								continue;
-							}
-
-							// Send to all connected users
-							((IServiceCapableConnection) cons).invoke("roomDisconnect", new Object[] { client },this);
-							log.debug("sending roomDisconnect to " + cons);
-						}
-					}
+			new MessageSender(scope, "roomDisconnect", client, this) {
+				@Override
+				public boolean filter(IConnection conn) {
+					Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+					boolean isScreen = rcl.isScreenClient();
+					if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
+						//going to terminate screen sharing started by this client
+						((IServiceCapableConnection) conn).invoke("stopStream", new Object[] { }, callback);
+					}					// TODO Auto-generated method stub
+					return rcl == null || isScreen;
 				}
-			}
+			}.start();
 
 			if (client.isMobile()) {
 				IApplication app = (IApplication)Application.get(OpenmeetingsVariables.wicketApplicationName);
 				app.exit(client.getPublicSID());
 			}
-			if (removeUserFromSessionList) {
-				sessionManager.removeClient(client.getStreamid(), null);
-			}
+			sessionManager.removeClient(client.getStreamid(), null);
 		} catch (Exception err) {
 			log.error("[roomLeaveByScope]", err);
 		}
@@ -800,32 +755,14 @@ public class ScopeApplicationAdapter ext
 	 */
 	@Override
 	public void streamBroadcastClose(IBroadcastStream stream) {
-
 		// Notify all the clients that the stream had been closed
 		log.debug("start streamBroadcastClose broadcast close: " + stream.getPublishedName());
 		try {
 			IConnection current = Red5.getConnectionLocal();
-			Client rcl = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-			sendClientBroadcastNotifications(stream, "closeStream", rcl);
-		} catch (Exception e) {
-			log.error("[streamBroadcastClose]", e);
-		}
-	}
-
-	/**
-	 * This method handles the notification room-based
-	 *
-	 * @return void
-	 *
-	 */
-	private void sendClientBroadcastNotifications(IBroadcastStream stream, String clientFunction, Client rc) {
-		try {
-			// Store the local so that we do not send notification to ourself back
-			IConnection current = Red5.getConnectionLocal();
-			String streamid = current.getClient().getId();
-			Client currentClient = sessionManager.getClientByStreamId(streamid, null);
+			String streamId = current.getClient().getId();
+			Client rcl = sessionManager.getClientByStreamId(streamId, null);
 
-			if (currentClient == null) {
+			if (rcl == null) {
 
 				// In case the client has already left(kicked) this message
 				// might be thrown later then the RoomLeave
@@ -837,55 +774,20 @@ public class ScopeApplicationAdapter ext
 
 			}
 			// Notify all the clients that the stream had been started
-			log.debug("sendClientBroadcastNotifications: " + stream.getPublishedName());
-			log.debug("sendClientBroadcastNotifications : " + currentClient + " " + currentClient.getStreamid());
-
+			log.debug("streamBroadcastClose : " + rcl + " " + rcl.getStreamid());
+			// this close stream event, stop the recording of this stream
+			if (rcl.getIsRecording()) {
+				log.debug("***  +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that");
+				recordingService.stopRecordingShowForClient(current.getScope(), rcl);
+			}
+			rcl.setBroadCastID(-1);
+			rcl.setIsBroadcasting(false);
+			rcl.setAvsettings("n");
+			sessionManager.updateClientByStreamId(streamId, rcl, false, null);
 			// Notify all clients of the same scope (room)
-			for (IConnection conn : current.getScope().getClientConnections()) {
-				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")) {
-								Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-								if (clientFunction.equals("closeStream") && rcl.getIsRecording()) {
-									log.debug("*** stopRecordingShowForClient Any Client is Recording - stop that");
-									// StreamService.stopRecordingShowForClient(conn,
-									// currentClient,
-									// rcl.getRoomRecordingName(), false);
-									recordingService.stopRecordingShowForClient(conn, currentClient);
-								}
-								// Don't notify current client
-								current.ping();
-							}
-							continue;
-						} else {
-							Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-							if (rcl != null) {
-								if (rcl.isScreenClient()) {
-									// continue;
-								} else {
-									log.debug("is this users still alive? :" + rcl);
-									IServiceCapableConnection iStream = (IServiceCapableConnection) conn;
-									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");
-									recordingService.stopRecordingShowForClient(conn, currentClient);
-								}
-							}
-						}
-					}
-				}
-			}
-		} catch (Exception err) {
-			log.error("[sendClientBroadcastNotifications]", err);
+			sendMessageToCurrentScope("closeStream", rcl, false);
+		} catch (Exception e) {
+			log.error("[streamBroadcastClose]", e);
 		}
 	}
 
@@ -1528,18 +1430,18 @@ public class ScopeApplicationAdapter ext
 	 * <li>do not send to connections where no RoomClient is registered</li>
 	 * </ul>
 	 *
-	 * @param remoteMethodName The method to be called
-	 * @param newMessage parameters
+	 * @param method The method to be called
+	 * @param msg parameters
 	 * @param sendSelf send to the current client as well
 	 * @param sendScreen send to the current client as well
 	 */
-	public void sendMessageToCurrentScope(final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
+	public void sendMessageToCurrentScope(final String method, final Object msg, final boolean sendSelf, final boolean sendScreen) {
 		IConnection conn = Red5.getConnectionLocal();
 		if (conn == null) {
-			log.warn(String.format("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' %s, %s", remoteMethodName, newMessage));
+			log.warn("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' {}, {}", method, msg);
 			return;
 		}
-		sendMessageToCurrentScope(conn.getScope().getName(), remoteMethodName, newMessage, sendSelf, sendScreen);
+		sendMessageToCurrentScope(conn.getScope().getName(), method, msg, sendSelf, sendScreen);
 	}
 
 	public void sendMessageToCurrentScope(final String scopeName, final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
@@ -1548,7 +1450,7 @@ public class ScopeApplicationAdapter ext
 			public boolean filter(IConnection conn) {
 				IClient client = conn.getClient();
 				return (!sendScreen && SessionVariablesUtil.isScreenClient(client))
-						|| (!sendSelf && client.getId().equals(current.getClient().getId()));
+						|| (!sendSelf && current != null && client.getId().equals(current.getClient().getId()));
 			}
 		}.start();
 	}
@@ -1556,27 +1458,27 @@ public class ScopeApplicationAdapter ext
 	public static abstract class MessageSender extends Thread {
 		final IScope scope;
 		final IConnection current;
-		final String remoteMethodName;
-		final Object newMessage;
+		final String method;
+		final Object msg;
 		final IPendingServiceCallback callback;
 
 		public MessageSender(final String remoteMethodName, final Object newMessage, IPendingServiceCallback callback) {
 			this((IScope)null, remoteMethodName, newMessage, callback);
 		}
 
-		public MessageSender(IScope _scope, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
-			this(Red5.getConnectionLocal(), _scope, remoteMethodName, newMessage, callback);
+		public MessageSender(IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
+			this(Red5.getConnectionLocal(), _scope, method, msg, callback);
 		}
 
-		public MessageSender(IConnection current, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
-			this(current, null, remoteMethodName, newMessage, callback);
+		public MessageSender(IConnection current, String method, Object msg, IPendingServiceCallback callback) {
+			this(current, null, method, msg, callback);
 		}
 
-		public MessageSender(IConnection current, IScope _scope, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
+		public MessageSender(IConnection current, IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
 			this.current = current;
-			scope = _scope == null ? current.getScope() : _scope;
-			this.remoteMethodName = remoteMethodName;
-			this.newMessage = newMessage;
+			scope = _scope == null && current != null ? current.getScope() : _scope;
+			this.method = method;
+			this.msg = msg;
 			this.callback = callback;
 		}
 
@@ -1586,10 +1488,10 @@ public class ScopeApplicationAdapter ext
 		public void run() {
 			try {
 				if (scope == null) {
-					log.debug(String.format("[MessageSender] -> 'Unable to send message to NULL scope' %s, %s", remoteMethodName, newMessage));
+					log.debug("[MessageSender] -> 'Unable to send message to NULL scope' {}, {}", method, msg);
 				} else {
 					if (log.isTraceEnabled()) {
-						log.trace(String.format("[MessageSender] -> 'sending message' %s, %s", remoteMethodName, newMessage));
+						log.trace("[MessageSender] -> 'sending message' {}, {}", method, msg);
 					}
 					// Send to all Clients of that Scope(Room)
 					int count = 0;
@@ -1598,16 +1500,16 @@ public class ScopeApplicationAdapter ext
 							if (filter(conn)) {
 								continue;
 							}
-							((IServiceCapableConnection) conn).invoke(remoteMethodName, new Object[] { newMessage }, callback);
+							((IServiceCapableConnection) conn).invoke(method, new Object[] { msg }, callback);
 							count++;
 						}
 					}
 					if (log.isTraceEnabled()) {
-						log.trace(String.format("[MessageSender] -> 'sending message to %s clients, DONE' %s", count, remoteMethodName));
+						log.trace("[MessageSender] -> 'sending message to {} clients, DONE' {}", count, method);
 					}
 				}
 			} catch (Exception err) {
-				log.error(String.format("[MessageSender -> %s, %s]", remoteMethodName, newMessage), err);
+				log.error(String.format("[MessageSender -> %s, %s]", method, msg), err);
 			}
 		}
 	}

Modified: openmeetings/application/branches/3.2.x/openmeetings-flash/src/main/swf/video/editRecordStreamSWF10.lzx
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-flash/src/main/swf/video/editRecordStreamSWF10.lzx?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-flash/src/main/swf/video/editRecordStreamSWF10.lzx (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-flash/src/main/swf/video/editRecordStreamSWF10.lzx Fri Mar 10 10:19:06 2017
@@ -189,10 +189,14 @@
 	<![CDATA[
 		//Initialize and get eventually stored property
 		var dev = canvas.commonVideoViewContent.getAvSetting(prop);
+		if ($debug) Debug.write("fillDeviceList:: ", prop, dev);
 
 		//Get all availible devices
 		var foundStoredDev = null;
 		combo.addItem(canvas.getLabelName(159), -1);
+		if ("-1" == dev) {
+			foundStoredDev = "-1";
+		}
 		for (var eg = 0; eg < list.length; ++eg) {
 			combo.addItem(list[eg], eg);
 			var r = "" + eg;

Modified: openmeetings/application/branches/3.2.x/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java Fri Mar 10 10:19:06 2017
@@ -429,7 +429,7 @@ public class UserManager implements IUse
 						scopeName = rcl.getRoomId().toString();
 					}
 					IScope currentScope = scopeApplicationAdapter.getRoomScope(scopeName);
-					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 					Map<Integer, String> messageObj = new HashMap<>();
 					messageObj.put(0, "kick");
@@ -465,7 +465,7 @@ public class UserManager implements IUse
 				messageObj.put(0, "kick");
 				scopeApplicationAdapter.sendMessageById(messageObj, rcl.getStreamid(), currentScope);
 
-				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 				return true;
 			}

Modified: openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java Fri Mar 10 10:19:06 2017
@@ -283,6 +283,8 @@ public class Application extends Authent
 					client = new Client(rcl, getBean(UserDao.class));
 					addOnlineUser(client);
 					if (rcl.getRoomId() != null) {
+						client.setCam(0);
+						client.setMic(0);
 						addUserToRoom(client);
 						//FIXME TODO unify this
 						WebSocketHelper.sendRoom(new RoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.roomEnter));
@@ -299,6 +301,12 @@ public class Application extends Authent
 			rcl.setIsMod(client.hasRight(Right.moderator));
 			rcl.setCanVideo(client.hasRight(Right.video) && client.isCamEnabled() && client.hasActivity(Activity.broadcastV));
 			rcl.setCanDraw(client.hasRight(Right.whiteBoard));
+			if (client.hasActivity(Activity.broadcastA) && client.getMic() < 0) {
+				client.remove(Activity.broadcastA);
+			}
+			if (client.hasActivity(Activity.broadcastV) && client.getCam() < 0) {
+				client.remove(Activity.broadcastV);
+			}
 			if (client.hasActivity(Activity.broadcastA) || client.hasActivity(Activity.broadcastV)) {
 				if (forceSize || rcl.getVWidth() == 0 || rcl.getVHeight() == 0) {
 					rcl.setVWidth(client.getWidth());
@@ -403,13 +411,15 @@ public class Application extends Authent
 	}
 
 	public static Client removeUserFromRoom(Client c) {
-		log.debug("Removing online room client: {}, room: {}", c.getUid(), c.getRoomId());
-		if (c.getRoomId() != null) {
-			Set<String> clients = ROOMS.get(c.getRoomId());
+		Long roomId = c.getRoomId();
+		log.debug("Removing online room client: {}, room: {}", c.getUid(), roomId);
+		if (roomId != null) {
+			Set<String> clients = ROOMS.get(roomId);
 			if (clients != null) {
 				clients.remove(c.getUid());
 				c.setRoomId(null);
 			}
+			getBean(ScopeApplicationAdapter.class).roomLeaveByScope(c.getUid(), roomId);
 			c.getActivities().clear();
 			c.clearRights();
 		}

Modified: openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java Fri Mar 10 10:19:06 2017
@@ -84,6 +84,7 @@ import org.apache.wicket.protocol.ws.api
 import org.apache.wicket.protocol.ws.api.message.AbstractClientMessage;
 import org.apache.wicket.protocol.ws.api.message.ClosedMessage;
 import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
+import org.apache.wicket.protocol.ws.api.message.ErrorMessage;
 import org.apache.wicket.protocol.ws.api.message.TextMessage;
 import org.apache.wicket.util.time.Duration;
 import org.red5.logging.Red5LoggerFactory;
@@ -251,6 +252,12 @@ public class MainPanel extends Panel {
 				closeHandler(msg);
 			}
 
+			@Override
+			protected void onError(WebSocketRequestHandler handler, ErrorMessage msg) {
+				super.onError(handler, msg);
+				closeHandler(msg);
+			}
+
 			private void closeHandler(AbstractClientMessage msg) {
 				//no chance to stop pingTimer here :(
 				log.debug("WebSocketBehavior::closeHandler [uid: {}, session: {}, key: {}]", client.getUid(), msg.getSessionId(), msg.getKey());

Modified: openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java (original)
+++ openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/MainService.java Fri Mar 10 10:19:06 2017
@@ -242,29 +242,6 @@ public class MainService implements IPen
 		return new Long(-1);
 	}
 
-	/**
-	 * clear this session id
-	 *
-	 * @param sid
-	 * @return string value if completed
-	 */
-	public Long logoutUser(String sid) {
-		try {
-			Sessiondata sd = sessionDao.check(sid);
-			IConnection current = Red5.getConnectionLocal();
-			Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-
-			scopeApplicationAdapter.roomLeaveByScope(currentClient,current.getScope(), false);
-
-			currentClient.setUserObject(null, null, null, null);
-
-			return userManager.logout(sid, sd.getUserId());
-		} catch (Exception err) {
-			log.error("[logoutUser]",err);
-		}
-		return -1L;
-	}
-
 	public List<Configuration> getGeneralOptions() {
 		try {
 			return configurationDao.get("exclusive.audio.keycode", CONFIG_SIP_ENABLED, CONFIG_MAX_UPLOAD_SIZE_KEY, "mute.keycode", CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY);

Modified: openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java (original)
+++ openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java Fri Mar 10 10:19:06 2017
@@ -248,7 +248,7 @@ public class RecordingService implements
 	 *
 	 * @param conn
 	 */
-	public void stopRecordingShow(IConnection conn, String broadcastId, Long metaId) {
+	public void stopRecordingShow(IScope scope, String broadcastId, Long metaId) {
 		try {
 			if (metaId == null) {
 				// this should be fixed, can be useful for debugging, after all this is an error
@@ -256,10 +256,10 @@ public class RecordingService implements
 				log.error("recordingMetaDataId is null");
 			}
 
-			log.debug("** stopRecordingShow: " + conn);
-			log.debug("### Stop recording show for broadcastId: " + broadcastId + " || " + conn.getScope().getContextPath());
+			log.debug("** stopRecordingShow: " + scope);
+			log.debug("### Stop recording show for broadcastId: " + broadcastId + " || " + scope.getContextPath());
 
-			Object streamToClose = scopeApplicationAdapter.getBroadcastStream(conn.getScope(), broadcastId);
+			Object streamToClose = scopeApplicationAdapter.getBroadcastStream(scope, broadcastId);
 
 			StreamListener listenerAdapter = streamListeners.get(metaId);
 
@@ -327,14 +327,14 @@ public class RecordingService implements
 						if (rcl.isScreenClient()) {
 							if (rcl.getRecordingId() != null && rcl.isScreenPublishStarted()) {
 								// Stop FLV Recording
-								stopRecordingShow(conn, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
+								stopRecordingShow(scope, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
 
 								// Update Meta Data
 								metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
 							}
 						} else if (rcl.getAvsettings().equals("av") || rcl.getAvsettings().equals("a") || rcl.getAvsettings().equals("v")) {
 
-							stopRecordingShow(conn, String.valueOf(rcl.getBroadCastID()).toString(), rcl.getRecordingMetaDataId());
+							stopRecordingShow(scope, String.valueOf(rcl.getBroadCastID()).toString(), rcl.getRecordingMetaDataId());
 
 							// Update Meta Data
 							metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
@@ -397,7 +397,7 @@ public class RecordingService implements
 		return null;
 	}
 
-	public void stopRecordingShowForClient(IConnection conn, Client rcl) {
+	public void stopRecordingShowForClient(IScope scope, Client rcl) {
 		try {
 			// this cannot be handled here, as to stop a stream and to leave a
 			// room is not
@@ -414,7 +414,7 @@ public class RecordingService implements
 					// FIXME: Is there really a need to stop it manually if the
 					// user just
 					// stops the stream?
-					stopRecordingShow(conn, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
+					stopRecordingShow(scope, rcl.getStreamPublishName(), rcl.getRecordingMetaDataId());
 
 					// Update Meta Data
 					metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());
@@ -424,7 +424,7 @@ public class RecordingService implements
 
 				// FIXME: Is there really a need to stop it manually if the user
 				// just stops the stream?
-				stopRecordingShow(conn, String.valueOf(rcl.getBroadCastID()), rcl.getRecordingMetaDataId());
+				stopRecordingShow(scope, String.valueOf(rcl.getBroadCastID()), rcl.getRecordingMetaDataId());
 
 				// Update Meta Data
 				metaDataDao.updateEndDate(rcl.getRecordingMetaDataId(), new Date());

Modified: openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java (original)
+++ openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/UserService.java Fri Mar 10 10:19:06 2017
@@ -146,7 +146,7 @@ public class UserService implements IUse
 					messageObj.put(0, "kick");
 					scopeApplicationAdapter.sendMessageById(messageObj, streamid, currentScope);
 
-					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 					return true;
 				} else {
@@ -199,7 +199,7 @@ public class UserService implements IUse
 				messageObj.put(0, "kick");
 
 				scopeApplicationAdapter.sendMessageById(messageObj, rcl.getStreamid(), currentScope);
-				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 				return true;
 			}

Modified: openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java (original)
+++ openmeetings/application/trunk/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java Fri Mar 10 10:19:06 2017
@@ -443,7 +443,7 @@ public class ScopeApplicationAdapter ext
 					returnMap.put("alreadyPublished", true);
 				}
 
-				log.debug(String.format("screen x,y,width,height %s,%s,%s,%s", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight()));
+				log.debug("screen x,y,width,height {},{},{},{}", client.getVX(), client.getVY(), client.getVWidth(), client.getVHeight());
 
 				if (startStreaming) {
 					if (!alreadyStreaming) {
@@ -559,43 +559,27 @@ public class ScopeApplicationAdapter ext
 	@Override
 	public void roomLeave(IClient client, IScope room) {
 		try {
-			log.debug(String.format("roomLeave %s %s %s %s", client.getId(), room.getClients().size(), room.getContextPath(), room.getName()));
+			log.debug("[roomLeave] {} {} {} {}", client.getId(), room.getClients().size(), room.getContextPath(), room.getName());
 
-			Client currentClient = sessionManager.getClientByStreamId(client.getId(), null);
+			Client rcl = sessionManager.getClientByStreamId(client.getId(), null);
 
 			// The Room Client can be null if the Client left the room by using
 			// logicalRoomLeave
-			if (currentClient != null) {
+			if (rcl != null) {
 				log.debug("currentClient IS NOT NULL");
-				roomLeaveByScope(currentClient, room, true);
+				roomLeaveByScope(rcl, room);
 			}
 		} 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 void logicalRoomLeave() {
-		log.debug("logicalRoomLeave ");
-		try {
-			IConnection current = Red5.getConnectionLocal();
-			String streamid = current.getClient().getId();
-
-			log.debug(streamid + " is leaving");
-
-			Client currentClient = sessionManager.getClientByStreamId(streamid, null);
-
-			roomLeaveByScope(currentClient, current.getScope(), true);
-		} catch (Exception err) {
-			log.error("[logicalRoomLeave]", err);
+	public void roomLeaveByScope(String uid, Long roomId) {
+		Client rcl = sessionManager.getClientByPublicSID(uid, null);
+		IScope scope = getRoomScope("" + roomId);
+		log.debug("[roomLeaveByScope] {} {} {} {}", uid, roomId, rcl, scope);
+		if (rcl != null && scope != null) {
+			roomLeaveByScope(rcl, scope);
 		}
 	}
 
@@ -609,9 +593,9 @@ public class ScopeApplicationAdapter ext
 	 * @param client
 	 * @param scope
 	 */
-	public void roomLeaveByScope(Client client, IScope scope, boolean removeUserFromSessionList) {
+	public void roomLeaveByScope(Client client, IScope scope) {
 		try {
-			log.debug("currentClient " + client);
+			log.debug("[roomLeaveByScope] currentClient " + client);
 			Long roomId = client.getRoomId();
 
 			if (client.isScreenClient() && client.isStartStreaming()) {
@@ -642,59 +626,30 @@ public class ScopeApplicationAdapter ext
 					client.setIsRecording(true);
 				}
 			}
+			recordingService.stopRecordingShowForClient(scope, client);
 
 			// 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 " + scope);
 
-			if (scope != null && scope.getClientConnections() != null) {
-				// Notify Users of the current Scope
-				for (IConnection cons : scope.getClientConnections()) {
-					if (cons != null && cons instanceof IServiceCapableConnection) {
-						log.debug("sending roomDisconnect to {}  client id {}", cons, cons.getClient().getId());
-
-						Client rcl = sessionManager.getClientByStreamId(cons.getClient().getId(), null);
-
-						// Check if the Client does still exist on the list
-						if (rcl == null) {
-							log.debug("For this StreamId: " + cons.getClient().getId() + " There is no Client in the List anymore");
-							continue;
-						}
-
-						//Do not send back to sender, but actually all other clients should receive this message swagner 01.10.2009
-						if (!client.getStreamid().equals(rcl.getStreamid())) {
-							// add Notification if another user isrecording
-							log.debug("###########[roomLeaveByScope]");
-							if (rcl.getIsRecording()) {
-								log.debug("*** roomLeave Any Client is Recording - stop that");
-								recordingService.stopRecordingShowForClient(cons, client);
-							}
-
-							boolean isScreen = rcl.isScreenClient();
-							if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
-								//going to terminate screen sharing started by this client
-								((IServiceCapableConnection) cons).invoke("stopStream", new Object[] { },this);
-								continue;
-							} else if (isScreen) {
-								// screen sharing clients do not receive events
-								continue;
-							}
-
-							// Send to all connected users
-							((IServiceCapableConnection) cons).invoke("roomDisconnect", new Object[] { client },this);
-							log.debug("sending roomDisconnect to " + cons);
-						}
-					}
+			new MessageSender(scope, "roomDisconnect", client, this) {
+				@Override
+				public boolean filter(IConnection conn) {
+					Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
+					boolean isScreen = rcl.isScreenClient();
+					if (isScreen && client.getPublicSID().equals(rcl.getStreamPublishName())) {
+						//going to terminate screen sharing started by this client
+						((IServiceCapableConnection) conn).invoke("stopStream", new Object[] { }, callback);
+					}					// TODO Auto-generated method stub
+					return rcl == null || isScreen;
 				}
-			}
+			}.start();
 
 			if (client.isMobile()) {
 				IApplication app = (IApplication)Application.get(OpenmeetingsVariables.wicketApplicationName);
 				app.exit(client.getPublicSID());
 			}
-			if (removeUserFromSessionList) {
-				sessionManager.removeClient(client.getStreamid(), null);
-			}
+			sessionManager.removeClient(client.getStreamid(), null);
 		} catch (Exception err) {
 			log.error("[roomLeaveByScope]", err);
 		}
@@ -800,32 +755,14 @@ public class ScopeApplicationAdapter ext
 	 */
 	@Override
 	public void streamBroadcastClose(IBroadcastStream stream) {
-
 		// Notify all the clients that the stream had been closed
 		log.debug("start streamBroadcastClose broadcast close: " + stream.getPublishedName());
 		try {
 			IConnection current = Red5.getConnectionLocal();
-			Client rcl = sessionManager.getClientByStreamId(current.getClient().getId(), null);
-			sendClientBroadcastNotifications(stream, "closeStream", rcl);
-		} catch (Exception e) {
-			log.error("[streamBroadcastClose]", e);
-		}
-	}
-
-	/**
-	 * This method handles the notification room-based
-	 *
-	 * @return void
-	 *
-	 */
-	private void sendClientBroadcastNotifications(IBroadcastStream stream, String clientFunction, Client rc) {
-		try {
-			// Store the local so that we do not send notification to ourself back
-			IConnection current = Red5.getConnectionLocal();
-			String streamid = current.getClient().getId();
-			Client currentClient = sessionManager.getClientByStreamId(streamid, null);
+			String streamId = current.getClient().getId();
+			Client rcl = sessionManager.getClientByStreamId(streamId, null);
 
-			if (currentClient == null) {
+			if (rcl == null) {
 
 				// In case the client has already left(kicked) this message
 				// might be thrown later then the RoomLeave
@@ -837,55 +774,20 @@ public class ScopeApplicationAdapter ext
 
 			}
 			// Notify all the clients that the stream had been started
-			log.debug("sendClientBroadcastNotifications: " + stream.getPublishedName());
-			log.debug("sendClientBroadcastNotifications : " + currentClient + " " + currentClient.getStreamid());
-
+			log.debug("streamBroadcastClose : " + rcl + " " + rcl.getStreamid());
+			// this close stream event, stop the recording of this stream
+			if (rcl.getIsRecording()) {
+				log.debug("***  +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that");
+				recordingService.stopRecordingShowForClient(current.getScope(), rcl);
+			}
+			rcl.setBroadCastID(-1);
+			rcl.setIsBroadcasting(false);
+			rcl.setAvsettings("n");
+			sessionManager.updateClientByStreamId(streamId, rcl, false, null);
 			// Notify all clients of the same scope (room)
-			for (IConnection conn : current.getScope().getClientConnections()) {
-				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")) {
-								Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-								if (clientFunction.equals("closeStream") && rcl.getIsRecording()) {
-									log.debug("*** stopRecordingShowForClient Any Client is Recording - stop that");
-									// StreamService.stopRecordingShowForClient(conn,
-									// currentClient,
-									// rcl.getRoomRecordingName(), false);
-									recordingService.stopRecordingShowForClient(conn, currentClient);
-								}
-								// Don't notify current client
-								current.ping();
-							}
-							continue;
-						} else {
-							Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
-							if (rcl != null) {
-								if (rcl.isScreenClient()) {
-									// continue;
-								} else {
-									log.debug("is this users still alive? :" + rcl);
-									IServiceCapableConnection iStream = (IServiceCapableConnection) conn;
-									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");
-									recordingService.stopRecordingShowForClient(conn, currentClient);
-								}
-							}
-						}
-					}
-				}
-			}
-		} catch (Exception err) {
-			log.error("[sendClientBroadcastNotifications]", err);
+			sendMessageToCurrentScope("closeStream", rcl, false);
+		} catch (Exception e) {
+			log.error("[streamBroadcastClose]", e);
 		}
 	}
 
@@ -1528,18 +1430,18 @@ public class ScopeApplicationAdapter ext
 	 * <li>do not send to connections where no RoomClient is registered</li>
 	 * </ul>
 	 *
-	 * @param remoteMethodName The method to be called
-	 * @param newMessage parameters
+	 * @param method The method to be called
+	 * @param msg parameters
 	 * @param sendSelf send to the current client as well
 	 * @param sendScreen send to the current client as well
 	 */
-	public void sendMessageToCurrentScope(final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
+	public void sendMessageToCurrentScope(final String method, final Object msg, final boolean sendSelf, final boolean sendScreen) {
 		IConnection conn = Red5.getConnectionLocal();
 		if (conn == null) {
-			log.warn(String.format("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' %s, %s", remoteMethodName, newMessage));
+			log.warn("[sendMessageToCurrentScope] -> 'Unable to send message using NULL connection' {}, {}", method, msg);
 			return;
 		}
-		sendMessageToCurrentScope(conn.getScope().getName(), remoteMethodName, newMessage, sendSelf, sendScreen);
+		sendMessageToCurrentScope(conn.getScope().getName(), method, msg, sendSelf, sendScreen);
 	}
 
 	public void sendMessageToCurrentScope(final String scopeName, final String remoteMethodName, final Object newMessage, final boolean sendSelf, final boolean sendScreen) {
@@ -1548,7 +1450,7 @@ public class ScopeApplicationAdapter ext
 			public boolean filter(IConnection conn) {
 				IClient client = conn.getClient();
 				return (!sendScreen && SessionVariablesUtil.isScreenClient(client))
-						|| (!sendSelf && client.getId().equals(current.getClient().getId()));
+						|| (!sendSelf && current != null && client.getId().equals(current.getClient().getId()));
 			}
 		}.start();
 	}
@@ -1556,27 +1458,27 @@ public class ScopeApplicationAdapter ext
 	public static abstract class MessageSender extends Thread {
 		final IScope scope;
 		final IConnection current;
-		final String remoteMethodName;
-		final Object newMessage;
+		final String method;
+		final Object msg;
 		final IPendingServiceCallback callback;
 
 		public MessageSender(final String remoteMethodName, final Object newMessage, IPendingServiceCallback callback) {
 			this((IScope)null, remoteMethodName, newMessage, callback);
 		}
 
-		public MessageSender(IScope _scope, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
-			this(Red5.getConnectionLocal(), _scope, remoteMethodName, newMessage, callback);
+		public MessageSender(IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
+			this(Red5.getConnectionLocal(), _scope, method, msg, callback);
 		}
 
-		public MessageSender(IConnection current, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
-			this(current, null, remoteMethodName, newMessage, callback);
+		public MessageSender(IConnection current, String method, Object msg, IPendingServiceCallback callback) {
+			this(current, null, method, msg, callback);
 		}
 
-		public MessageSender(IConnection current, IScope _scope, String remoteMethodName, Object newMessage, IPendingServiceCallback callback) {
+		public MessageSender(IConnection current, IScope _scope, String method, Object msg, IPendingServiceCallback callback) {
 			this.current = current;
-			scope = _scope == null ? current.getScope() : _scope;
-			this.remoteMethodName = remoteMethodName;
-			this.newMessage = newMessage;
+			scope = _scope == null && current != null ? current.getScope() : _scope;
+			this.method = method;
+			this.msg = msg;
 			this.callback = callback;
 		}
 
@@ -1586,10 +1488,10 @@ public class ScopeApplicationAdapter ext
 		public void run() {
 			try {
 				if (scope == null) {
-					log.debug(String.format("[MessageSender] -> 'Unable to send message to NULL scope' %s, %s", remoteMethodName, newMessage));
+					log.debug("[MessageSender] -> 'Unable to send message to NULL scope' {}, {}", method, msg);
 				} else {
 					if (log.isTraceEnabled()) {
-						log.trace(String.format("[MessageSender] -> 'sending message' %s, %s", remoteMethodName, newMessage));
+						log.trace("[MessageSender] -> 'sending message' {}, {}", method, msg);
 					}
 					// Send to all Clients of that Scope(Room)
 					int count = 0;
@@ -1598,16 +1500,16 @@ public class ScopeApplicationAdapter ext
 							if (filter(conn)) {
 								continue;
 							}
-							((IServiceCapableConnection) conn).invoke(remoteMethodName, new Object[] { newMessage }, callback);
+							((IServiceCapableConnection) conn).invoke(method, new Object[] { msg }, callback);
 							count++;
 						}
 					}
 					if (log.isTraceEnabled()) {
-						log.trace(String.format("[MessageSender] -> 'sending message to %s clients, DONE' %s", count, remoteMethodName));
+						log.trace("[MessageSender] -> 'sending message to {} clients, DONE' {}", count, method);
 					}
 				}
 			} catch (Exception err) {
-				log.error(String.format("[MessageSender -> %s, %s]", remoteMethodName, newMessage), err);
+				log.error(String.format("[MessageSender -> %s, %s]", method, msg), err);
 			}
 		}
 	}

Modified: openmeetings/application/trunk/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java (original)
+++ openmeetings/application/trunk/openmeetings-service/src/main/java/org/apache/openmeetings/service/user/UserManager.java Fri Mar 10 10:19:06 2017
@@ -429,7 +429,7 @@ public class UserManager implements IUse
 						scopeName = rcl.getRoomId().toString();
 					}
 					IScope currentScope = scopeApplicationAdapter.getRoomScope(scopeName);
-					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+					scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 					Map<Integer, String> messageObj = new HashMap<>();
 					messageObj.put(0, "kick");
@@ -465,7 +465,7 @@ public class UserManager implements IUse
 				messageObj.put(0, "kick");
 				scopeApplicationAdapter.sendMessageById(messageObj, rcl.getStreamid(), currentScope);
 
-				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope, true);
+				scopeApplicationAdapter.roomLeaveByScope(rcl, currentScope);
 
 				return true;
 			}

Modified: openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java (original)
+++ openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java Fri Mar 10 10:19:06 2017
@@ -283,6 +283,8 @@ public class Application extends Authent
 					client = new Client(rcl, getBean(UserDao.class));
 					addOnlineUser(client);
 					if (rcl.getRoomId() != null) {
+						client.setCam(0);
+						client.setMic(0);
 						addUserToRoom(client);
 						//FIXME TODO unify this
 						WebSocketHelper.sendRoom(new RoomMessage(client.getRoomId(), client.getUserId(), RoomMessage.Type.roomEnter));
@@ -299,6 +301,12 @@ public class Application extends Authent
 			rcl.setIsMod(client.hasRight(Right.moderator));
 			rcl.setCanVideo(client.hasRight(Right.video) && client.isCamEnabled() && client.hasActivity(Activity.broadcastV));
 			rcl.setCanDraw(client.hasRight(Right.whiteBoard));
+			if (client.hasActivity(Activity.broadcastA) && client.getMic() < 0) {
+				client.remove(Activity.broadcastA);
+			}
+			if (client.hasActivity(Activity.broadcastV) && client.getCam() < 0) {
+				client.remove(Activity.broadcastV);
+			}
 			if (client.hasActivity(Activity.broadcastA) || client.hasActivity(Activity.broadcastV)) {
 				if (forceSize || rcl.getVWidth() == 0 || rcl.getVHeight() == 0) {
 					rcl.setVWidth(client.getWidth());
@@ -403,13 +411,15 @@ public class Application extends Authent
 	}
 
 	public static Client removeUserFromRoom(Client c) {
-		log.debug("Removing online room client: {}, room: {}", c.getUid(), c.getRoomId());
-		if (c.getRoomId() != null) {
-			Set<String> clients = ROOMS.get(c.getRoomId());
+		Long roomId = c.getRoomId();
+		log.debug("Removing online room client: {}, room: {}", c.getUid(), roomId);
+		if (roomId != null) {
+			Set<String> clients = ROOMS.get(roomId);
 			if (clients != null) {
 				clients.remove(c.getUid());
 				c.setRoomId(null);
 			}
+			getBean(ScopeApplicationAdapter.class).roomLeaveByScope(c.getUid(), roomId);
 			c.getActivities().clear();
 			c.clearRights();
 		}

Modified: openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java?rev=1786321&r1=1786320&r2=1786321&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java (original)
+++ openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java Fri Mar 10 10:19:06 2017
@@ -84,6 +84,7 @@ import org.apache.wicket.protocol.ws.api
 import org.apache.wicket.protocol.ws.api.message.AbstractClientMessage;
 import org.apache.wicket.protocol.ws.api.message.ClosedMessage;
 import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
+import org.apache.wicket.protocol.ws.api.message.ErrorMessage;
 import org.apache.wicket.protocol.ws.api.message.TextMessage;
 import org.apache.wicket.util.time.Duration;
 import org.red5.logging.Red5LoggerFactory;
@@ -251,6 +252,12 @@ public class MainPanel extends Panel {
 				closeHandler(msg);
 			}
 
+			@Override
+			protected void onError(WebSocketRequestHandler handler, ErrorMessage msg) {
+				super.onError(handler, msg);
+				closeHandler(msg);
+			}
+
 			private void closeHandler(AbstractClientMessage msg) {
 				//no chance to stop pingTimer here :(
 				log.debug("WebSocketBehavior::closeHandler [uid: {}, session: {}, key: {}]", client.getUid(), msg.getSessionId(), msg.getKey());