diff --git a/app.js b/app.js
index 8584d50d5..9e3699236 100644
--- a/app.js
+++ b/app.js
@@ -15,6 +15,11 @@ var ssrc2jid = {};
*/
var ssrc2videoType = {};
var videoSrcToSsrc = {};
+/**
+ * Currently focused video "src"(displayed in large video).
+ * @type {String}
+ */
+var focusedVideoSrc = null;
var mutedAudios = {};
var localVideoSrc = null;
@@ -353,7 +358,65 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
}
});
+/**
+ * Returns the JID of the user to whom given videoSrc belongs.
+ * @param videoSrc the video "src" identifier.
+ * @returns {null | String} the JID of the user to whom given videoSrc
+ * belongs.
+ */
+function getJidFromVideoSrc(videoSrc)
+{
+ if (videoSrc === localVideoSrc)
+ return connection.emuc.myroomjid;
+
+ var ssrc = videoSrcToSsrc[videoSrc];
+ if (!ssrc)
+ {
+ return null;
+ }
+ return ssrc2jid[ssrc];
+}
+
+/**
+ * Gets the selector of video thumbnail container for the user identified by
+ * given userJid
+ * @param userJid user's Jid for whom we want to get the video container.
+ */
+function getParticipantContainer(userJid)
+{
+ if (!userJid)
+ return null;
+
+ if (userJid === connection.emuc.myroomjid)
+ return $("#localVideoContainer");
+ else
+ return $("#participant_" + Strophe.getResourceFromJid(userJid));
+}
+
function handleVideoThumbClicked(videoSrc) {
+ // Restore style for previously focused video
+ var oldContainer =
+ getParticipantContainer(
+ getJidFromVideoSrc(focusedVideoSrc));
+ if (oldContainer)
+ oldContainer.removeClass("videoContainerFocused");
+
+ // Unlock
+ if (focusedVideoSrc === videoSrc)
+ {
+ focusedVideoSrc = null;
+ return;
+ }
+
+ // Lock new video
+ focusedVideoSrc = videoSrc;
+
+ var userJid = getJidFromVideoSrc(videoSrc);
+ if (userJid)
+ {
+ var container = getParticipantContainer(userJid);
+ container.addClass("videoContainerFocused");
+ }
$(document).trigger("video.selected", [false]);
@@ -499,7 +562,8 @@ $(document).bind('callactive.jingle', function (event, videoelem, sid) {
videoelem.show();
resizeThumbnails();
- updateLargeVideo(videoelem.attr('src'), 1);
+ if (!focusedVideoSrc)
+ updateLargeVideo(videoelem.attr('src'), 1);
showFocusIndicator();
}
@@ -618,6 +682,16 @@ $(document).bind('left.muc', function (event, jid) {
}
}, 10);
+ // Unlock large video
+ if (focusedVideoSrc)
+ {
+ if (getJidFromVideoSrc(focusedVideoSrc) === jid)
+ {
+ console.info("Focused video owner has left the conference");
+ focusedVideoSrc = null;
+ }
+ }
+
connection.jingle.terminateByJid(jid);
if (focus == null
diff --git a/css/videolayout_default.css b/css/videolayout_default.css
index 7c7823100..44011d027 100644
--- a/css/videolayout_default.css
+++ b/css/videolayout_default.css
@@ -52,6 +52,10 @@
z-index: 3;
}
+#remoteVideos .videocontainer.videoContainerFocused {
+ border: 3px solid #388396;
+}
+
#localVideoWrapper {
display:inline-block;
-webkit-mask-box-image: url(../images/videomask.svg);
diff --git a/data_channels.js b/data_channels.js
index e63015b89..8ab0a4b1b 100644
--- a/data_channels.js
+++ b/data_channels.js
@@ -1,4 +1,4 @@
-/* global connection, Strophe, updateLargeVideo*/
+/* global connection, Strophe, updateLargeVideo, focusedVideoSrc*/
/**
* Callback triggered by PeerConnection when new data channel is opened
* on the bridge.
@@ -30,7 +30,7 @@ function onDataChannel(event)
console.info("Got Data Channel Message:", msgData, dataChannel);
// Active speaker event
- if (msgData.indexOf('activeSpeaker') === 0)
+ if (msgData.indexOf('activeSpeaker') === 0 && !focusedVideoSrc)
{
// Endpoint ID from the bridge
var endpointId = msgData.split(":")[1];