diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts index bae20f2d..1801c505 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts @@ -1,11 +1,9 @@ import { Component, HostListener, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core'; -import { Publisher, PublisherProperties } from 'openvidu-browser'; -import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/OpenViduError'; +import { PublisherProperties } from 'openvidu-browser'; import { Subscription } from 'rxjs'; import { CustomDevice } from '../../models/device.model'; import { ILogger } from '../../models/logger.model'; -import { ParticipantAbstractModel, ParticipantProperties } from '../../models/participant.model'; -import { ActionService } from '../../services/action/action.service'; +import { ParticipantAbstractModel } from '../../models/participant.model'; import { DeviceService } from '../../services/device/device.service'; import { LayoutService } from '../../services/layout/layout.service'; import { LoggerService } from '../../services/logger/logger.service'; @@ -96,19 +94,13 @@ export class PreJoinComponent implements OnInit, OnDestroy { const pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror }; await this.openviduService.republishTrack(pp); - this.cameraSelected = videoSource; - this.deviceSrv.setCameraSelected(this.cameraSelected); - } - if (this.isVideoMuted) { - // Publish Webcam video - this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true); - this.isVideoMuted = false; + this.deviceSrv.setCameraSelected(videoSource); + this.cameraSelected = this.deviceSrv.getCameraSelected(); } } async onMicrophoneSelected(event: any) { const audioSource = event?.value; - // Is New deviceId different than older? if (this.deviceSrv.needUpdateAudioTrack(audioSource)) { //TODO: Uncomment this when replaceTrack issue is fixed // const pp: PublisherProperties = { audioSource, videoSource: false }; @@ -118,83 +110,21 @@ export class PreJoinComponent implements OnInit, OnDestroy { const pp: PublisherProperties = { videoSource: this.cameraSelected.device, audioSource, mirror }; await this.openviduService.republishTrack(pp); - this.microphoneSelected = audioSource; - this.deviceSrv.setMicSelected(this.microphoneSelected); - } - if (this.isAudioMuted) { - // Enable microphone - this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), true); - this.isAudioMuted = true; + this.deviceSrv.setMicSelected(audioSource); + this.microphoneSelected = this.deviceSrv.getMicrophoneSelected(); } } - toggleCam() { + async toggleCam() { const publish = this.isVideoMuted; - this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publish); - - if (this.participantService.haveICameraAndScreenActive()) { - // Cam will not published, disable webcam with screensharing active - this.participantService.disableWebcamStream(); - this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publish); - } else if (this.participantService.isOnlyMyScreenActive()) { - // Cam will be published, enable webcam - this.participantService.enableWebcamStream(); - } - + await this.openviduService.muteVideo(publish); this.isVideoMuted = !this.isVideoMuted; this.storageSrv.setVideoMuted(this.isVideoMuted); } - // async toggleScreenShare() { - // // Disabling screenShare - // if (this.participantService.haveICameraAndScreenActive()) { - // this.participantService.disableScreenUser(); - // return; - // } - - // // Enabling screenShare - // if (this.participantService.isOnlyMyCameraActive()) { - // const willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive(); - // const hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.isAudioMuted; - // const properties: PublisherProperties = { - // videoSource: ScreenType.SCREEN, - // audioSource: this.hasAudioDevices ? undefined : null, - // publishVideo: true, - // publishAudio: hasAudio, - // mirror: false - // }; - // const screenPublisher = await this.openviduService.initPublisher(undefined, properties); - - // screenPublisher.on('accessAllowed', (event) => { - // screenPublisher.stream - // .getMediaStream() - // .getVideoTracks()[0] - // .addEventListener('ended', () => { - // this.log.d('Clicked native stop button. Stopping screen sharing'); - // this.toggleScreenShare(); - // }); - // this.participantService.activeMyScreenShare(screenPublisher); - // if (!this.participantService.hasCameraVideoActive()) { - // this.participantService.disableWebcamUser(); - // } - // }); - - // screenPublisher.on('accessDenied', (error: any) => { - // if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') { - // this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing'); - // } - // }); - // return; - // } - - // // Disabling screnShare and enabling webcam - // this.participantService.enableWebcamUser(); - // this.participantService.disableScreenUser(); - // } - toggleMic() { const publish = this.isAudioMuted; - this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), publish); + this.openviduService.muteAudio(publish); this.isAudioMuted = !this.isAudioMuted; this.storageSrv.setAudioMuted(this.isAudioMuted); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts index 1040f384..424bac85 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts @@ -19,8 +19,7 @@ import { DocumentService } from '../../services/document/document.service'; import { OpenViduService } from '../../services/openvidu/openvidu.service'; import { LoggerService } from '../../services/logger/logger.service'; import { ILogger } from '../../models/logger.model'; -import { ScreenType } from '../../models/video-type.model'; -import { PublisherProperties, Session } from 'openvidu-browser'; +import { Session } from 'openvidu-browser'; import { ActionService } from '../../services/action/action.service'; import { DeviceService } from '../../services/device/device.service'; import { ChatMessage } from '../../models/chat.model'; @@ -286,16 +285,13 @@ export class ToolbarComponent implements OnInit, OnDestroy { /** * @ignore */ - toggleMicrophone() { + async toggleMicrophone() { this.onMicrophoneButtonClicked.emit(); - - if (this.participantService.isMyCameraActive()) { - this.openviduService.publishAudio( - this.participantService.getMyCameraPublisher(), - !this.participantService.hasCameraAudioActive() - ); - } else { - this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive()); + try { + await this.openviduService.muteAudio(!this.isAudioActive); + } catch (error) { + this.log.e('There was an error toggling microphone:', error.code, error.message); + this.actionService.openDialog('There was an error toggling camera', error?.error || error?.message); } } @@ -307,32 +303,10 @@ export class ToolbarComponent implements OnInit, OnDestroy { try { const publishVideo = !this.participantService.hasCameraVideoActive(); - const publishAudio = this.participantService.hasCameraAudioActive(); - // Disabling webcam - if (this.participantService.haveICameraAndScreenActive()) { - this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publishVideo); - this.participantService.disableWebcamStream(); - this.openviduService.unpublish(this.participantService.getMyCameraPublisher()); - this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publishAudio); - return; - } - // Enabling webcam - if (this.participantService.isOnlyMyScreenActive()) { - const hasAudio = this.participantService.hasScreenAudioActive(); - - if (!this.openviduService.isWebcamSessionConnected()) { - await this.openviduService.connectSession(this.openviduService.getWebcamSession(), this.tokenService.getWebcamToken()); - } - await this.openviduService.publish(this.participantService.getMyCameraPublisher()); - this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), false); - this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), hasAudio); - this.participantService.enableWebcamStream(); - } - // Muting/unmuting webcam - this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publishVideo); + await this.openviduService.muteVideo(publishVideo); } catch (error) { this.log.e('There was an error toggling camera:', error.code, error.message); - this.actionService.openDialog('There was an error toggling camera:', error?.error || error?.message); + this.actionService.openDialog('There was an error toggling camera', error?.error || error?.message); } } @@ -343,76 +317,12 @@ export class ToolbarComponent implements OnInit, OnDestroy { this.onScreenshareButtonClicked.emit(); try { - // Disabling screenShare - if (this.participantService.haveICameraAndScreenActive()) { - this.participantService.disableScreenStream(); - this.openviduService.unpublish(this.participantService.getMyScreenPublisher()); - return; - } - - // Enabling screenShare - if (this.participantService.isOnlyMyCameraActive()) { - const willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive(); - const hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.participantService.hasCameraAudioActive(); - const properties: PublisherProperties = { - videoSource: ScreenType.SCREEN, - audioSource: this.hasAudioDevices ? undefined : null, - publishVideo: true, - publishAudio: hasAudio, - mirror: false - }; - const screenPublisher = await this.openviduService.initPublisher(undefined, properties); - - screenPublisher.once('accessAllowed', async (event) => { - // Listen to event fired when native stop button is clicked - screenPublisher.stream - .getMediaStream() - .getVideoTracks()[0] - .addEventListener('ended', () => { - this.log.d('Clicked native stop button. Stopping screen sharing'); - this.toggleScreenShare(); - }); - this.log.d('ACCESS ALOWED screenPublisher'); - this.participantService.activeMyScreenShare(screenPublisher); - - if (!this.openviduService.isScreenSessionConnected()) { - await this.openviduService.connectSession( - this.openviduService.getScreenSession(), - this.tokenService.getScreenToken() - ); - } - await this.openviduService.publish(this.participantService.getMyScreenPublisher()); - // this.openviduService.sendNicknameSignal(); - if (!this.participantService.hasCameraVideoActive()) { - // Disabling webcam - this.participantService.disableWebcamStream(); - this.openviduService.unpublish(this.participantService.getMyCameraPublisher()); - } - }); - - screenPublisher.once('accessDenied', (error: any) => { - this.log.e(error); - if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') { - this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing'); - } - }); - return; - } - - // Disabling screnShare and enabling webcam - const hasAudio = this.participantService.hasScreenAudioActive(); - if (!this.openviduService.isWebcamSessionConnected()) { - await this.openviduService.connectSession(this.openviduService.getWebcamSession(), this.tokenService.getWebcamToken()); - } - await this.openviduService.publish(this.participantService.getMyCameraPublisher()); - this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), false); - this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), hasAudio); - this.participantService.enableWebcamStream(); - this.participantService.disableScreenStream(); - this.openviduService.unpublish(this.participantService.getMyScreenPublisher()); + await this.openviduService.toggleScreenshare(); } catch (error) { - this.log.e('There was an error toggling screen share:', error.code, error.message); - this.actionService.openDialog('There was an error toggling screen share:', error?.error || error?.message); + this.log.e('There was an error toggling screen share', error.code, error.message); + if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') { + this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing'); + } } } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts index 533a3b75..a8f95a74 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts @@ -3,8 +3,6 @@ import { ParticipantProperties, StreamModel } from '../models/participant.model' export interface OpenViduAngularConfig { production?: boolean, participantFactory?: ParticipantFactoryFunction, - webcomponent?: boolean - } export type ParticipantFactoryFunction = (props: ParticipantProperties, streamModel: StreamModel) => any; \ No newline at end of file diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts index 2b9ee3f1..c6dca29d 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts @@ -1,14 +1,5 @@ import { Injectable } from '@angular/core'; -import { - Connection, - OpenVidu, - OpenViduError, - OpenViduErrorName, - Publisher, - PublisherProperties, - Session, - SignalOptions -} from 'openvidu-browser'; +import { Connection, OpenVidu, Publisher, PublisherProperties, Session, SignalOptions } from 'openvidu-browser'; import { LoggerService } from '../logger/logger.service'; @@ -18,8 +9,9 @@ import { OpenViduAngularConfigService } from '../config/openvidu-angular.config. import { PlatformService } from '../platform/platform.service'; import { DeviceService } from '../device/device.service'; import { CameraType } from '../../models/device.model'; -import { VideoType } from '../../models/video-type.model'; +import { ScreenType, VideoType } from '../../models/video-type.model'; import { ParticipantService } from '../participant/participant.service'; +import { TokenService } from '../token/token.service'; @Injectable({ providedIn: 'root' @@ -41,7 +33,8 @@ export class OpenViduService { protected platformService: PlatformService, protected loggerSrv: LoggerService, private participantService: ParticipantService, - protected deviceService: DeviceService + protected deviceService: DeviceService, + protected tokenService: TokenService ) { this.log = this.loggerSrv.get('OpenViduService'); } @@ -51,6 +44,11 @@ export class OpenViduService { */ initialize() { this.OV = new OpenVidu(); + this.OV.setAdvancedConfiguration({ + publisherSpeakingEventsOptions: { + interval: 50 + } + }); if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode(); this.webcamSession = this.OV.initSession(); @@ -163,8 +161,6 @@ export class OpenViduService { // audioSource = undefined; } - // const videoSource = publishVideo ? this.deviceService.getCameraSelected().device : false; - // const audioSource = publishAudio ? this.deviceService.getMicrophoneSelected().device : false; const mirror = this.deviceService.getCameraSelected() && this.deviceService.getCameraSelected().type === CameraType.FRONT; const properties: PublisherProperties = { videoSource, @@ -213,10 +209,10 @@ export class OpenViduService { /** * @internal */ - unpublish(publisher: Publisher): void { + private unpublish(publisher: Publisher): void { if (!!publisher) { if (publisher === this.participantService.getMyCameraPublisher()) { - this.publishAudio(this.participantService.getMyScreenPublisher(), this.participantService.hasCameraAudioActive()); + this.publishAudioAux(this.participantService.getMyScreenPublisher(), this.participantService.hasCameraAudioActive()); this.webcamSession.unpublish(publisher); } else if (publisher === this.participantService.getMyScreenPublisher()) { this.screenSession.unpublish(publisher); @@ -224,20 +220,127 @@ export class OpenViduService { } } - /** - * @internal - */ - publishVideo(publisher: Publisher, value: boolean): void { - if (!!publisher) { - publisher.publishVideo(value); - this.participantService.updateLocalParticipant(); + async muteVideo(mute: boolean): Promise { + const publishAudio = this.participantService.hasCameraAudioActive(); + // const publishVideo = !this.participantService.hasCameraVideoActive(); + + // Disabling webcam + if (this.participantService.haveICameraAndScreenActive()) { + this.publishVideoAux(this.participantService.getMyCameraPublisher(), mute); + this.participantService.disableWebcamStream(); + this.unpublish(this.participantService.getMyCameraPublisher()); + this.publishAudioAux(this.participantService.getMyScreenPublisher(), publishAudio); + } else if (this.participantService.isOnlyMyScreenActive()) { + // Enabling webcam + const hasAudio = this.participantService.hasScreenAudioActive(); + console.warn('Es audio activo?', hasAudio); + if (!this.isWebcamSessionConnected()) { + //TODO: should be the token in th participant? + await this.connectSession(this.getWebcamSession(), this.tokenService.getWebcamToken()); + } + await this.publish(this.participantService.getMyCameraPublisher()); + this.publishVideoAux(this.participantService.getMyCameraPublisher(), true); + this.publishAudioAux(this.participantService.getMyScreenPublisher(), false); + this.publishAudioAux(this.participantService.getMyCameraPublisher(), hasAudio); + this.participantService.enableWebcamStream(); + } else { + // Muting/unmuting webcam + this.publishVideoAux(this.participantService.getMyCameraPublisher(), mute); } } /** * @internal */ - publishAudio(publisher: Publisher, value: boolean): void { + private publishVideoAux(publisher: Publisher, value: boolean): void { + if (!!publisher) { + publisher.publishVideo(value); + this.participantService.updateLocalParticipant(); + } + } + + async muteAudio(value: boolean): Promise { + if (this.participantService.isMyCameraActive()) { + if (this.participantService.isMyScreenActive() && this.participantService.hasScreenAudioActive()) { + this.publishAudioAux(this.participantService.getMyScreenPublisher(), false); + } + + this.publishAudioAux(this.participantService.getMyCameraPublisher(), value); + } else { + this.publishAudioAux(this.participantService.getMyScreenPublisher(), value); + } + } + + async toggleScreenshare() { + if (this.participantService.haveICameraAndScreenActive()) { + // Disabling screenShare + this.participantService.disableScreenStream(); + this.unpublish(this.participantService.getMyScreenPublisher()); + } else if (this.participantService.isOnlyMyCameraActive()) { + // I only have the camera published + const hasAudioDevicesAvailable = this.deviceService.hasAudioDeviceAvailable(); + const willWebcamBePresent = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive(); + const hasAudio = willWebcamBePresent ? false : hasAudioDevicesAvailable && this.participantService.hasCameraAudioActive(); + + console.warn('will be audio active', hasAudio); + const properties: PublisherProperties = { + videoSource: ScreenType.SCREEN, + audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : null, + publishVideo: true, + publishAudio: hasAudio, + mirror: false + }; + const screenPublisher = await this.initPublisher(undefined, properties); + + screenPublisher.once('accessAllowed', async () => { + // Listen to event fired when native stop button is clicked + screenPublisher.stream + .getMediaStream() + .getVideoTracks()[0] + .addEventListener('ended', async () => { + this.log.d('Clicked native stop button. Stopping screen sharing'); + await this.toggleScreenshare(); + }); + + // Enabling screenShare + this.participantService.activeMyScreenShare(screenPublisher); + + if (!this.isScreenSessionConnected()) { + await this.connectSession(this.getScreenSession(), this.tokenService.getScreenToken()); + } + await this.publish(this.participantService.getMyScreenPublisher()); + if (!this.participantService.hasCameraVideoActive()) { + // Disabling webcam + this.participantService.disableWebcamStream(); + this.unpublish(this.participantService.getMyCameraPublisher()); + } + }); + + screenPublisher.once('accessDenied', (error: any) => { + return Promise.reject(error); + }); + } else { + // I only have my screenshare active and I have no camera or it is muted + const hasAudio = this.participantService.hasScreenAudioActive(); + + // Enable webcam + if (!this.isWebcamSessionConnected()) { + await this.connectSession(this.getWebcamSession(), this.tokenService.getWebcamToken()); + } + await this.publish(this.participantService.getMyCameraPublisher()); + this.publishAudioAux(this.participantService.getMyCameraPublisher(), hasAudio); + this.participantService.enableWebcamStream(); + + // Disabling screenshare + this.participantService.disableScreenStream(); + this.unpublish(this.participantService.getMyScreenPublisher()); + } + } + + /** + * @internal + */ + private publishAudioAux(publisher: Publisher, value: boolean): void { if (!!publisher) { publisher.publishAudio(value); this.participantService.updateLocalParticipant(); @@ -368,32 +471,33 @@ export class OpenViduService { } } - private async createMediaStream(pp: PublisherProperties): Promise { - let mediaStream: MediaStream; - const isFirefoxPlatform = this.platformService.isFirefox(); - const isReplacingAudio = !!pp.audioSource; - const isReplacingVideo = !!pp.videoSource; + //TODO: Uncomment this section when replaceTrack issue is fixed + // private async createMediaStream(pp: PublisherProperties): Promise { + // let mediaStream: MediaStream; + // const isFirefoxPlatform = this.platformService.isFirefox(); + // const isReplacingAudio = !!pp.audioSource; + // const isReplacingVideo = !!pp.videoSource; - try { - mediaStream = await this.OV.getUserMedia(pp); - } catch (error) { - if ((error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) { - if (isFirefoxPlatform) { - this.log.w('The device requested is not available. Restoring the older one'); - // The track requested is not available so we are getting the old tracks ids for recovering the track - if (isReplacingVideo) { - pp.videoSource = this.deviceService.getCameraSelected().device; - } else if (isReplacingAudio) { - pp.audioSource = this.deviceService.getMicrophoneSelected().device; - } - mediaStream = await this.OV.getUserMedia(pp); - // TODO show error alert informing that the new device is not available - } - } - } finally { - return mediaStream; - } - } + // try { + // mediaStream = await this.OV.getUserMedia(pp); + // } catch (error) { + // if ((error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) { + // if (isFirefoxPlatform) { + // this.log.w('The device requested is not available. Restoring the older one'); + // // The track requested is not available so we are getting the old tracks ids for recovering the track + // if (isReplacingVideo) { + // pp.videoSource = this.deviceService.getCameraSelected().device; + // } else if (isReplacingAudio) { + // pp.audioSource = this.deviceService.getMicrophoneSelected().device; + // } + // mediaStream = await this.OV.getUserMedia(pp); + // // TODO show error alert informing that the new device is not available + // } + // } + // } finally { + // return mediaStream; + // } + // } /** * @internal diff --git a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts index d26e489c..df76a2f0 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts @@ -41,6 +41,7 @@ export * from './lib/config/openvidu-angular.config'; export * from './lib/models/logger.model'; export * from './lib/models/video-type.model'; export * from './lib/models/notification-options.model'; +export * from './lib/models/token.model'; // Pipes export * from './lib/pipes/participant.pipe';