From 17960063ebba78b0f261a67a58d5791cef2b44fc Mon Sep 17 00:00:00 2001 From: Taymoor Khan Date: Tue, 17 Dec 2019 16:40:41 -0800 Subject: [PATCH] feat(MeetingJsonAdapter): implement getStream Co-authored-by: arash koushkebaghi --- src/adapters/MeetingsJSONAdapter.js | 44 +++++++++++++++++------- src/adapters/MeetingsJSONAdapter.test.js | 17 +++++++-- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/adapters/MeetingsJSONAdapter.js b/src/adapters/MeetingsJSONAdapter.js index 2ae0ba031..1920e10fd 100644 --- a/src/adapters/MeetingsJSONAdapter.js +++ b/src/adapters/MeetingsJSONAdapter.js @@ -1,4 +1,4 @@ -import {concat, from, fromEvent, Observable} from 'rxjs'; +import {concat, from, fromEvent, Observable, of} from 'rxjs'; import {filter, flatMap, map} from 'rxjs/operators'; import {MeetingsAdapter, MeetingControlState} from '@webex/component-adapter-interfaces'; @@ -92,13 +92,27 @@ export default class MeetingsJSONAdapter extends MeetingsAdapter { observer.complete(); }); - // Attach local media stream if meeting `localVideo` property is not `null`. + // Attach media stream if any of the meeting's media stream properties are not `null`. // We can not attach the MediaStream object in a JSON module, the work needs // to be done here. - const getMeetingWithLocalMedia$ = getMeeting$.pipe( + const getMeetingWithMedia$ = getMeeting$.pipe( + /* eslint-disable no-confusing-arrow */ flatMap((meeting) => - from(this.getLocalVideo()).pipe(map((localVideo) => (meeting.localVideo ? {...meeting, localVideo} : meeting))) + meeting.localVideo + ? from(this.getStream({video: true, audio: false})).pipe(map((localVideo) => ({...meeting, localVideo}))) + : of(meeting) + ), + flatMap((meeting) => + meeting.remoteVideo + ? from(this.getStream({video: true, audio: false})).pipe(map((remoteVideo) => ({...meeting, remoteVideo}))) + : of(meeting) + ), + flatMap((meeting) => + meeting.remoteAudio + ? from(this.getStream({video: false, audio: true})).pipe(map((remoteAudio) => ({...meeting, remoteAudio}))) + : of(meeting) ) + /* eslint-enable no-confusing-arrow */ ); // Send updates on the meeting when a mute event is triggered @@ -107,25 +121,29 @@ export default class MeetingsJSONAdapter extends MeetingsAdapter { map((event) => event.detail) ); - return concat(getMeetingWithLocalMedia$, muteEvent$); + return concat(getMeetingWithMedia$, muteEvent$); } /** - * Returns a MediaStream object obtained from local user media. + * Returns a MediaStream object obtained from user local media. + * @param {MediaStreamConstraints} constraints an object specifying the types of the media to request * @returns {MediaStream} */ - async getLocalVideo() { - const constraints = { - video: true, - audio: false, - }; + async getStream(constraints) { let stream; try { - stream = await navigator.mediaDevices.getUserMedia(constraints); + const mediaStream = await navigator.mediaDevices.getUserMedia(constraints); + + // filter out either video or audio from a given constraints and return a new media stream + if (constraints.video) { + stream = new MediaStream([mediaStream.getVideoTracks()[0]]); + } else { + stream = new MediaStream([mediaStream.getAudioTracks()[0]]); + } } catch (reason) { // eslint-disable-next-line no-console - console.error('Meetings JSON adapter can not display the user local stream', reason); + console.error('Meetings JSON adapter can not display the local user stream', reason); } return stream; diff --git a/src/adapters/MeetingsJSONAdapter.test.js b/src/adapters/MeetingsJSONAdapter.test.js index ff64435db..0f975ec97 100644 --- a/src/adapters/MeetingsJSONAdapter.test.js +++ b/src/adapters/MeetingsJSONAdapter.test.js @@ -10,7 +10,6 @@ describe('Meetings JSON Adapter', () => { beforeEach(() => { [meetingID] = Object.keys(meetings); meetingsJSONAdapter = new MeetingsJSONAdapter(meetings); - meetingsJSONAdapter.getLocalVideo = jest.fn(() => Promise.resolve('mock-stream')); }); afterEach(() => { @@ -31,7 +30,21 @@ describe('Meetings JSON Adapter', () => { test('renders the local media if localVideo property is defined', (done) => { meetingsJSONAdapter.getMeeting('localVideo').subscribe((data) => { - expect(data.localVideo).toEqual('mock-stream'); + expect(data.localVideo).toEqual({control: 'video'}); + done(); + }); + }); + + test('renders the remote video if remoteVideo property is defined', (done) => { + meetingsJSONAdapter.getMeeting('remoteVideo').subscribe((data) => { + expect(data.remoteVideo).toEqual({control: 'video'}); + done(); + }); + }); + + test('renders the remote audio if remoteAudio property is defined', (done) => { + meetingsJSONAdapter.getMeeting('remoteAudio').subscribe((data) => { + expect(data.remoteAudio).toEqual({control: 'audio'}); done(); }); });