diff --git a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx index 0a080fa811238ae4417729b00e69409b2ea27aa6..21cfab534c23b843ccb1793a897ddd2fd5796a1c 100755 --- a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx @@ -109,6 +109,7 @@ class BreakoutJoinConfirmation extends Component { }, 'joining breakout room closed audio in the main room'); } + VideoService.storeDeviceIds(); VideoService.exitVideo(); if (UserListService.amIPresenter()) screenshareHasEnded(); if (url === '') { diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx index aad2ba112349e928c6b36a5348f8d50af233f124..b4c7219fee9ccdfb838a4cd3d0e522f9a74df5fe 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx @@ -248,6 +248,7 @@ class BreakoutRoom extends PureComponent { logCode: 'breakoutroom_join', extraInfo: { logType: 'user_action' }, }, 'joining breakout room closed audio in the main room'); + VideoService.storeDeviceIds(); VideoService.exitVideo(); if (UserListService.amIPresenter()) screenshareHasEnded(); } diff --git a/bigbluebutton-html5/imports/ui/components/media/container.jsx b/bigbluebutton-html5/imports/ui/components/media/container.jsx index 29988871900f42376062b5849b3a97802ac77857..61a94e95610f82baccc971a345f7dc1d2aded8ec 100755 --- a/bigbluebutton-html5/imports/ui/components/media/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/media/container.jsx @@ -16,6 +16,8 @@ import DefaultContent from '../presentation/default-content/component'; import ExternalVideoContainer from '../external-video-player/container'; import Storage from '../../services/storage/session'; import { withLayoutConsumer } from '/imports/ui/components/layout/context'; +import Auth from '/imports/ui/services/auth'; +import breakoutService from '/imports/ui/components/breakout-room/service'; const LAYOUT_CONFIG = Meteor.settings.public.layout; const KURENTO_CONFIG = Meteor.settings.public.kurento; @@ -106,6 +108,8 @@ class MediaContainer extends Component { } } +let userWasInBreakout = false; + export default withLayoutConsumer(withModalMounter(withTracker(() => { const { dataSaving } = Settings; const { viewParticipantsWebcams, viewScreenshare } = dataSaving; @@ -127,6 +131,31 @@ export default withLayoutConsumer(withModalMounter(withTracker(() => { data.children = <ScreenshareContainer />; } + const userIsInBreakout = breakoutService.getBreakoutUserIsIn(Auth.userID); + let deviceIds = Session.get('deviceIds'); + + if (!userIsInBreakout && userWasInBreakout && deviceIds && deviceIds !== '') { + /* used when re-sharing cameras after leaving a breakout room. + it is needed in cases where the user has more than one active camera + so we only share the second camera after the first + has finished loading (can't share more than one at the same time) */ + const canConnect = Session.get('canConnect'); + + deviceIds = deviceIds.split(','); + + if (canConnect) { + const deviceId = deviceIds.shift(); + + Session.set('canConnect', false); + Session.set('WebcamDeviceId', deviceId); + Session.set('deviceIds', deviceIds.join(',')); + + VideoService.joinVideo(deviceId); + } + } else { + userWasInBreakout = userIsInBreakout; + } + const { streams: usersVideo } = VideoService.getVideoStreams(); data.usersVideo = usersVideo; diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/service.js b/bigbluebutton-html5/imports/ui/components/video-provider/service.js index 8984d69bcdb2f44181f369ff4a5c5a388e9b9fe0..05e0196d817ede7a0453919c9f7f54289e631200 100755 --- a/bigbluebutton-html5/imports/ui/components/video-provider/service.js +++ b/bigbluebutton-html5/imports/ui/components/video-provider/service.js @@ -142,6 +142,22 @@ class VideoService { this.isConnected = true; } + storeDeviceIds() { + const streams = VideoStreams.find( + { + meetingId: Auth.meetingID, + userId: Auth.userID, + }, { fields: { deviceId: 1 } }, + ).fetch(); + + let deviceIds = []; + streams.forEach(s => { + deviceIds.push(s.deviceId); + } + ); + Session.set('deviceIds', deviceIds.join()); + } + exitVideo() { if (this.isConnected) { logger.info({ @@ -801,6 +817,7 @@ class VideoService { const videoService = new VideoService(); export default { + storeDeviceIds: () => videoService.storeDeviceIds(), exitVideo: () => videoService.exitVideo(), joinVideo: deviceId => videoService.joinVideo(deviceId), stopVideo: cameraId => videoService.stopVideo(cameraId), diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx index 1fcb49cc09afdaf532a47642d0db7ff2a83cc62f..21bb8333bdd9683277a297479f1ba7b4685cf3db 100755 --- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx @@ -122,6 +122,12 @@ class VideoListItem extends Component { const { videoIsReady } = this.state; if (!videoIsReady) this.setState({ videoIsReady: true }); window.dispatchEvent(new Event('resize')); + + /* used when re-sharing cameras after leaving a breakout room. + it is needed in cases where the user has more than one active camera + so we only share the second camera after the first + has finished loading (can't share more than one at the same time) */ + Session.set('canConnect', true); } getAvailableActions() {