Skip to content

Commit

Permalink
Merge pull request aullman#108 from prabhuvashwin/OPENTOK-42849
Browse files Browse the repository at this point in the history
OPENTOK-42849: Add force mute buttons to meet
  • Loading branch information
Ashwin V Prabhu authored Mar 22, 2021
2 parents 1bec448 + 7721a60 commit 0b72bc6
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 14 deletions.
1 change: 1 addition & 0 deletions plugins/screen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = (app, config) => {
room: req.param('room'),
chromeExtensionId: config.chromeExtensionId,
opentokJs: config.opentokJs,
tokenRole: req.query.tokenRole,
});
});
};
1 change: 1 addition & 0 deletions plugins/whiteboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = (app, config) => {
res.render('whiteboard', {
opentokJs: config.opentokJs,
room: req.param('room'),
tokenRole: req.query.tokenRole,
});
});
};
37 changes: 37 additions & 0 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ button.red {
background-color: #C04B4B;
}

button.gray {
background-color: #808080;
}

button.unread {

}
Expand Down Expand Up @@ -486,6 +490,39 @@ body.mouse-move #bottomBar, body.mouse-move #statusMessages, body.mouse-move #co
opacity: 1;
}

mute-audio {
color: white;
cursor: pointer;
position: absolute;
}

mute-audio .audio-icon {
font-size: 20px;
padding: 0;
margin: 0;
}

ot-subscriber mute-audio {
position: absolute;
transition-property: top,bottom,opacity;
transition-duration: .5s;
transition-timing-function: ease-in;
opacity: 0;
top: -25px;
right: 152px;
margin-top: 2px;
z-index: 99;
}

ot-layout > :hover mute-audio, ot-layout button.OT_mode-on ~ mute-audio {
top: 0;
opacity: 1;
}

ot-subscriber mute-audio .audio-icon {
font-size: 32px;
}

/* Mute Video Directive */
mute-video {
color: white;
Expand Down
4 changes: 3 additions & 1 deletion server/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = (app, config, redis, ot, redirectSSL) => {
const room = req.param('room');
const apiKey = req.param('apiKey');
const secret = req.param('secret');
const tokenRole = req.query.tokenRole;
res.format({
json() {
const goToRoom = (err, sessionId, pApiKey, pSecret) => {
Expand All @@ -60,7 +61,7 @@ module.exports = (app, config, redis, ot, redirectSSL) => {
apiKey: (pApiKey && pSecret) ? pApiKey : config.apiKey,
p2p: RoomStore.isP2P(room),
token: otSDK.generateToken(sessionId, {
role: 'publisher',
role: tokenRole || 'publisher',
}),
});
}
Expand All @@ -71,6 +72,7 @@ module.exports = (app, config, redis, ot, redirectSSL) => {
res.render('room', {
opentokJs: config.opentokJs,
room,
tokenRole,
chromeExtensionId: config.chromeExtensionId,
});
},
Expand Down
19 changes: 19 additions & 0 deletions src/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ angular.module('opentok-meet').controller('RoomCtrl', ['$scope', '$http', '$wind
$scope.publishing = !$scope.publishing;
};

$scope.forceMuteAll = () => {
$scope.session.forceMuteAll().then(() => {
console.log('forceMuteAll complete');
}).catch((error) => {
console.error('forceMuteAll failed', error);
});
};

$scope.forceMuteAllExcludingPublisherStream = () => {
const streamId = (OT.publishers.find() || {}).streamId;
const streams = (OT.sessions.find() || {}).streams;
const stream = streams ? streams.get(streamId) : undefined;
$scope.session.forceMuteAll([stream]).then(() => {
console.log('forceMuteAllExcludingPublisherStream complete');
}).catch((error) => {
console.error('forceMuteAllExcludingPublisherStream failed', error);
});
};

const startArchiving = () => {
$scope.archiving = true;
$http.post(`${baseURL + $scope.room}/startArchive`).then((response) => {
Expand Down
23 changes: 23 additions & 0 deletions src/js/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ angular.module('opentok-meet').directive('draggable', ['$document', '$window',
'title="{{mutedVideo ? \'Unmute Video\' : \'Mute Video\'}}"' +
'</i></div>',
}))
.directive('muteAudio', () => ({
restrict: 'E',
template: '<div><i class="audio-icon microphone icon-left ion ion-ios7-mic-off" ' +
'title="Mute Audio}}"></i></div>',
}))
.directive('muteSubscriber', ['OTSession', function muteSubscriber(OTSession) {
return {
restrict: 'A',
Expand All @@ -116,6 +121,24 @@ angular.module('opentok-meet').directive('draggable', ['$document', '$window',
},
};
}])
.directive('muteSubscriberAudio', ['OTSession', function muteSubscriberAudio(OTSession) {
return {
restrict: 'A',
link(scope, element) {
angular.element(element).on('click', () => {
const forceMuteStream = OTSession.session.forceMuteStream;
if (scope.stream) {
const pResponse = forceMuteStream(scope.stream);
pResponse.then(() => {
console.log('forceMuteStream success. Muted stream id: ', scope.stream.id);
}).catch((error) => {
console.error('forceMuteStream failed', error);
});
}
});
},
};
}])
.directive('mutePublisher', ['OTSession', function mutePublisher(OTSession) {
return {
restrict: 'A',
Expand Down
7 changes: 6 additions & 1 deletion src/js/login/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ angular.module('opentok-meet-login', [])
.controller('MainCtrl', ['$scope', '$window', function MainCtrl($scope, $window) {
$scope.room = '';
$scope.roomType = 'normal';
$scope.tokenRole = 'moderator';
$scope.advanced = false;
$scope.dtx = false;
$scope.joinRoom = () => {
let url = $window.location.href + encodeURIComponent($scope.room);
if ($scope.roomType !== 'normal') {
url += `/${$scope.roomType}`;
}
if ($scope.tokenRole) {
url += `?tokenRole=${$scope.tokenRole}`;
}
if ($scope.dtx) {
url += '?dtx=true';
const precursor = $scope.tokenRole ? '&' : '?';
url += `${precursor}dtx=true`;
}
$window.location.href = url;
};
Expand Down
6 changes: 3 additions & 3 deletions src/js/services.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Asynchronous fetching of the room. This is so that the mobile app can use the
// same controller. It doesn't know the room straight away
angular.module('opentok-meet').factory('RoomService', ['$http', 'baseURL', '$window', 'room',
function RoomService($http, baseURL, $window, room) {
angular.module('opentok-meet').factory('RoomService', ['$http', 'baseURL', '$window', 'room', 'tokenRole',
function RoomService($http, baseURL, $window, room, tokenRole) {
return {
getRoom() {
return $http.get(baseURL + room)
return $http.get(`${baseURL}${room}?tokenRole=${tokenRole}`)
.then(response => response.data)
.catch(response => response.data);
},
Expand Down
52 changes: 46 additions & 6 deletions tests/unit/login/controllerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,61 @@ describe('OpenTok Login Page', () => {
};
});

it('sets the url correctly for normal roomType', () => {
it('sets the url correctly for normal roomType, tokenRole defaults to moderator', () => {
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo');
expect(windowMock.location.href).toEqual('mockURL/foo?tokenRole=moderator');
});

it('sets the url correctly for whiteboard roomType', () => {
it('sets the url correctly for whiteboard roomType, tokenRole defaults to moderator', () => {
scope.roomType = 'whiteboard';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/whiteboard');
expect(windowMock.location.href).toEqual('mockURL/foo/whiteboard?tokenRole=moderator');
});

it('sets the url correctly for screen roomType', () => {
it('sets the url correctly for screen roomType, tokenRole defaults to moderator', () => {
scope.roomType = 'screen';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/screen');
expect(windowMock.location.href).toEqual('mockURL/foo/screen?tokenRole=moderator');
});

it('sets the url correctly for normal roomType, tokenRole=publisher', () => {
scope.tokenRole = 'publisher';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo?tokenRole=publisher');
});

it('sets the url correctly for whiteboard roomType, tokenRole=publisher', () => {
scope.roomType = 'whiteboard';
scope.tokenRole = 'publisher';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/whiteboard?tokenRole=publisher');
});

it('sets the url correctly for screen roomType, tokenRole=publisher', () => {
scope.roomType = 'screen';
scope.tokenRole = 'publisher';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/screen?tokenRole=publisher');
});

it('sets the url correctly for normal roomType, tokenRole=subscriber', () => {
scope.tokenRole = 'subscriber';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo?tokenRole=subscriber');
});

it('sets the url correctly for whiteboard roomType, tokenRole=subscriber', () => {
scope.roomType = 'whiteboard';
scope.tokenRole = 'subscriber';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/whiteboard?tokenRole=subscriber');
});

it('sets the url correctly for screen roomType, tokenRole=subscriber', () => {
scope.roomType = 'screen';
scope.tokenRole = 'subscriber';
scope.joinRoom();
expect(windowMock.location.href).toEqual('mockURL/foo/screen?tokenRole=subscriber');
});
});

Expand Down
5 changes: 4 additions & 1 deletion tests/unit/servicesSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ describe('RoomService', () => {
let baseURL;
let $httpBackend;
let room;
let tokenRole;

beforeEach(angular.mock.module('opentok-meet'));
beforeEach(() => {
baseURL = 'https://mock.url/';
windowMock = {
location: {},
};
tokenRole = 'moderator';
room = 'mockRoom';
angular.mock.module(($provide) => {
$provide.value('baseURL', baseURL);
$provide.value('room', room);
$provide.value('$window', windowMock);
$provide.value('tokenRole', tokenRole);
});
inject((_RoomService_, $injector) => {
RoomService = _RoomService_;
Expand Down Expand Up @@ -48,7 +51,7 @@ describe('RoomService', () => {
});

it('gets the room info and passes it along', (done) => {
$httpBackend.expectGET(baseURL + room)
$httpBackend.expectGET(`${baseURL}${room}?tokenRole=${tokenRole}`)
.respond(200, JSON.stringify(mockRoomData));
RoomService.getRoom().then((roomData) => {
expect(roomData).toEqual(mockRoomData);
Expand Down
6 changes: 6 additions & 0 deletions views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
</label>
</div>
<br>
<div id="tokenRole">
<label>Moderator<input type="radio" name="tokenRole" ng-model="tokenRole" value="moderator"><br></label>
<label>Publisher<input type="radio" name="tokenRole" ng-model="tokenRole" value="publisher"><br></label>
<label>Subscriber<input type="radio" name="tokenRole" ng-model="tokenRole" value="subscriber"><br></label>
</div>
<br>
<div id="roomTypeRadio">
<label>Normal<input type="radio" name="roomType" ng-model="roomType" value="normal"><br></label>
<label title="just use the whiteboard">Whiteboard only<input type="radio" name="roomType" ng-model="roomType" value="whiteboard"><br></label>
Expand Down
5 changes: 5 additions & 0 deletions views/room.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<expand-button></expand-button>
<zoom-button zoomed="expanded ? bigZoomed : zoomed"
ng-click="$emit('changeZoom', expanded);"></zoom-button>
<mute-audio mute-subscriber-audio></mute-audio>
</ot-subscriber>
<ot-whiteboard ng-show="showWhiteboard"
ng-if="connected"
Expand Down Expand Up @@ -134,6 +135,9 @@

<button type="button" name="muteMicrophone" muted-type="Audio" ng-if="publishing" mute-publisher ng-class="{green: mutedAudio, red: !mutedAudio, 'ion-ios7-mic-off': mutedAudio, 'ion-ios7-mic': !mutedAudio}" publisher-id="facePublisher" class="icon-left ion">Mic</button>

<button type="button" name="muteAll" id="muteAll" ng-click="forceMuteAll()" class="icon-left ion gray">Mute All</button>

<button type="button" name="muteAllExcludingPublishingStream" id="muteAllExcludingPublishingStream" ng-click="forceMuteAllExcludingPublisherStream()" class="icon-left ion gray">Mute All Excluding Publishing Stream</button>

<span id="publishUI">
<button name="publish" id="publishBtn" ng-click="togglePublish(true)" ng-class="{green: !publishing, red: publishing}" class="publish-btn icon-left ion ion-ios7-videocam" title="WebCam">{{ publishing ? 'Unpublish' : 'Publish HD'}}</button>
Expand All @@ -159,6 +163,7 @@
angular.module('opentok-meet').value({
room: '<%=room%>',
baseURL: '/',
tokenRole: '<%=tokenRole%>',
chromeExtensionId: '<%=chromeExtensionId%>'
});
</script>
Expand Down
3 changes: 2 additions & 1 deletion views/screen.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
angular.module('opentok-meet').value({
room: '<%=room%>',
chromeExtensionId: '<%=chromeExtensionId%>',
baseURL: '/'
baseURL: '/',
tokenRole: '<%=tokenRole%>',
});
</script>
</head>
Expand Down
3 changes: 2 additions & 1 deletion views/whiteboard.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
<script type="text/javascript">
angular.module('opentok-meet').value({
room: '<%=room%>',
baseURL: '/'
baseURL: '/',
tokenRole: '<%=tokenRole%>',
});
</script>
</head>
Expand Down

0 comments on commit 0b72bc6

Please sign in to comment.