<NME> public-api.ts
<BEF> /*
 * Public API Surface of openvidu-components-angular
 */

export * from './lib/openvidu-angular.module';

// Services
export * from './lib/services/openvidu/openvidu.service';
export * from './lib/services/participant/participant.service';
export * from './lib/services/chat/chat.service';
export * from './lib/services/action/action.service';
export * from './lib/services/layout/layout.service';
export * from './lib/services/panel/panel.service';
export * from './lib/services/recording/recording.service';

// Components
export * from './lib/components/videoconference/videoconference.component';
export * from './lib/components/toolbar/toolbar.component';
export * from './lib/components/panel/panel.component';
export * from './lib/components/panel/activities-panel/activities-panel.component';
export * from './lib/components/panel/chat-panel/chat-panel.component';
export * from './lib/components/panel/participants-panel/participants-panel/participants-panel.component';
export * from './lib/components/panel/participants-panel/participant-panel-item/participant-panel-item.component';
export * from './lib/components/layout/layout.component';
export * from './lib/components/stream/stream.component';
export * from './lib/admin/dashboard/dashboard.component';
export * from './lib/admin/login/login.component';

// Models
export * from './lib/models/participant.model';
export * from './lib/config/openvidu-angular.config';
export * from './lib/models/video-type.model';
export * from './lib/models/token.model';
export * from './lib/models/signal.model';
export * from './lib/models/panel.model';
export * from './lib/models/recording.model';

// Pipes
export * from './lib/pipes/participant.pipe';
export * from './lib/pipes/recording.pipe';
export * from './lib/models/logger.model';
export * from './lib/models/video-type.model';
export * from './lib/models/notification-options.model';

// Pipes
export * from './lib/pipes/participant.pipe';
export * from './lib/directives/api/toolbar.directive';
export * from './lib/directives/api/stream.directive';
export * from './lib/directives/api/videoconference.directive';
export * from './lib/directives/api/participant-panel-item.directive';
export * from './lib/directives/api/activities-panel.directive';
export * from './lib/directives/api/recording-activity.directive';
export * from './lib/directives/api/admin.directive';

<MSG> openvidu-components: Moved component logic to openvidu service

Moved toggle screen, toggle video and toggle audio logic from toolbar and prejoin component to openvidu service with the aim of avoiding code duplications and being able to provide a powerful method to the components user
<DFF> @@ -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';

{'commit': "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\nindex bae20f2d..1801c505 100644\n--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts\n+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/pre-join/pre-join.component.ts\n@@ -1,11 +1,9 @@\n import { Component, HostListener, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core';\n-import { Publisher, PublisherProperties } from 'openvidu-browser';\n-import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/OpenViduError';\n+import { PublisherProperties } from 'openvidu-browser';\n import { Subscription } from 'rxjs';\n import { CustomDevice } from '../../models/device.model';\n import { ILogger } from '../../models/logger.model';\n-import { ParticipantAbstractModel, ParticipantProperties } from '../../models/participant.model';\n-import { ActionService } from '../../services/action/action.service';\n+import { ParticipantAbstractModel } from '../../models/participant.model';\n import { DeviceService } from '../../services/device/device.service';\n import { LayoutService } from '../../services/layout/layout.service';\n import { LoggerService } from '../../services/logger/logger.service';\n@@ -96,19 +94,13 @@ export class PreJoinComponent implements OnInit, OnDestroy {\n \t\t\tconst pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror };\n \t\t\tawait this.openviduService.republishTrack(pp);\n \n-\t\t\tthis.cameraSelected = videoSource;\n-\t\t\tthis.deviceSrv.setCameraSelected(this.cameraSelected);\n-\t\t}\n-\t\tif (this.isVideoMuted) {\n-\t\t\t// Publish Webcam video\n-\t\t\tthis.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);\n-\t\t\tthis.isVideoMuted = false;\n+\t\t\tthis.deviceSrv.setCameraSelected(videoSource);\n+\t\t\tthis.cameraSelected = this.deviceSrv.getCameraSelected();\n \t\t}\n \t}\n \n \tasync onMicrophoneSelected(event: any) {\n \t\tconst audioSource = event?.value;\n-\t\t// Is New deviceId different than older?\n \t\tif (this.deviceSrv.needUpdateAudioTrack(audioSource)) {\n \t\t\t//TODO: Uncomment this when replaceTrack issue is fixed\n \t\t\t// const pp: PublisherProperties = { audioSource, videoSource: false };\n@@ -118,83 +110,21 @@ export class PreJoinComponent implements OnInit, OnDestroy {\n \t\t\tconst pp: PublisherProperties = { videoSource: this.cameraSelected.device, audioSource, mirror };\n \t\t\tawait this.openviduService.republishTrack(pp);\n \n-\t\t\tthis.microphoneSelected = audioSource;\n-\t\t\tthis.deviceSrv.setMicSelected(this.microphoneSelected);\n-\t\t}\n-\t\tif (this.isAudioMuted) {\n-\t\t\t// Enable microphone\n-\t\t\tthis.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), true);\n-\t\t\tthis.isAudioMuted = true;\n+\t\t\tthis.deviceSrv.setMicSelected(audioSource);\n+\t\t\tthis.microphoneSelected = this.deviceSrv.getMicrophoneSelected();\n \t\t}\n \t}\n \n-\ttoggleCam() {\n+\tasync toggleCam() {\n \t\tconst publish = this.isVideoMuted;\n-\t\tthis.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publish);\n-\n-\t\tif (this.participantService.haveICameraAndScreenActive()) {\n-\t\t\t// Cam will not published, disable webcam with screensharing active\n-\t\t\tthis.participantService.disableWebcamStream();\n-\t\t\tthis.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publish);\n-\t\t} else if (this.participantService.isOnlyMyScreenActive()) {\n-\t\t\t// Cam will be published, enable webcam\n-\t\t\tthis.participantService.enableWebcamStream();\n-\t\t}\n-\n+\t\tawait this.openviduService.muteVideo(publish);\n \t\tthis.isVideoMuted = !this.isVideoMuted;\n \t\tthis.storageSrv.setVideoMuted(this.isVideoMuted);\n \t}\n \n-\t// async toggleScreenShare() {\n-\t// \t// Disabling screenShare\n-\t// \tif (this.participantService.haveICameraAndScreenActive()) {\n-\t// \t\tthis.participantService.disableScreenUser();\n-\t// \t\treturn;\n-\t// \t}\n-\n-\t// \t// Enabling screenShare\n-\t// \tif (this.participantService.isOnlyMyCameraActive()) {\n-\t// \t\tconst willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive();\n-\t// \t\tconst hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.isAudioMuted;\n-\t// \t\tconst properties: PublisherProperties = {\n-\t// \t\t\tvideoSource: ScreenType.SCREEN,\n-\t// \t\t\taudioSource: this.hasAudioDevices ? undefined : null,\n-\t// \t\t\tpublishVideo: true,\n-\t// \t\t\tpublishAudio: hasAudio,\n-\t// \t\t\tmirror: false\n-\t// \t\t};\n-\t// \t\tconst screenPublisher = await this.openviduService.initPublisher(undefined, properties);\n-\n-\t// \t\tscreenPublisher.on('accessAllowed', (event) => {\n-\t// \t\t\tscreenPublisher.stream\n-\t// \t\t\t\t.getMediaStream()\n-\t// \t\t\t\t.getVideoTracks()[0]\n-\t// \t\t\t\t.addEventListener('ended', () => {\n-\t// \t\t\t\t\tthis.log.d('Clicked native stop button. Stopping screen sharing');\n-\t// \t\t\t\t\tthis.toggleScreenShare();\n-\t// \t\t\t\t});\n-\t// \t\t\tthis.participantService.activeMyScreenShare(screenPublisher);\n-\t// \t\t\tif (!this.participantService.hasCameraVideoActive()) {\n-\t// \t\t\t\tthis.participantService.disableWebcamUser();\n-\t// \t\t\t}\n-\t// \t\t});\n-\n-\t// \t\tscreenPublisher.on('accessDenied', (error: any) => {\n-\t// \t\t\tif (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {\n-\t// \t\t\t\tthis.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing');\n-\t// \t\t\t}\n-\t// \t\t});\n-\t// \t\treturn;\n-\t// \t}\n-\n-\t// \t// Disabling screnShare and enabling webcam\n-\t// \tthis.participantService.enableWebcamUser();\n-\t// \tthis.participantService.disableScreenUser();\n-\t// }\n-\n \ttoggleMic() {\n \t\tconst publish = this.isAudioMuted;\n-\t\tthis.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), publish);\n+\t\tthis.openviduService.muteAudio(publish);\n \t\tthis.isAudioMuted = !this.isAudioMuted;\n \t\tthis.storageSrv.setAudioMuted(this.isAudioMuted);\n \t}\ndiff --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\nindex 1040f384..424bac85 100644\n--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts\n+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts\n@@ -19,8 +19,7 @@ import { DocumentService } from '../../services/document/document.service';\n import { OpenViduService } from '../../services/openvidu/openvidu.service';\n import { LoggerService } from '../../services/logger/logger.service';\n import { ILogger } from '../../models/logger.model';\n-import { ScreenType } from '../../models/video-type.model';\n-import { PublisherProperties, Session } from 'openvidu-browser';\n+import { Session } from 'openvidu-browser';\n import { ActionService } from '../../services/action/action.service';\n import { DeviceService } from '../../services/device/device.service';\n import { ChatMessage } from '../../models/chat.model';\n@@ -286,16 +285,13 @@ export class ToolbarComponent implements OnInit, OnDestroy {\n \t/**\n \t * @ignore\n \t */\n-\ttoggleMicrophone() {\n+\tasync toggleMicrophone() {\n \t\tthis.onMicrophoneButtonClicked.emit();\n-\n-\t\tif (this.participantService.isMyCameraActive()) {\n-\t\t\tthis.openviduService.publishAudio(\n-\t\t\t\tthis.participantService.getMyCameraPublisher(),\n-\t\t\t\t!this.participantService.hasCameraAudioActive()\n-\t\t\t);\n-\t\t} else {\n-\t\t\tthis.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive());\n+\t\ttry {\n+\t\t\tawait this.openviduService.muteAudio(!this.isAudioActive);\n+\t\t} catch (error) {\n+\t\t\tthis.log.e('There was an error toggling microphone:', error.code, error.message);\n+\t\t\tthis.actionService.openDialog('There was an error toggling camera', error?.error || error?.message);\n \t\t}\n \t}\n \n@@ -307,32 +303,10 @@ export class ToolbarComponent implements OnInit, OnDestroy {\n \n \t\ttry {\n \t\t\tconst publishVideo = !this.participantService.hasCameraVideoActive();\n-\t\t\tconst publishAudio = this.participantService.hasCameraAudioActive();\n-\t\t\t// Disabling webcam\n-\t\t\tif (this.participantService.haveICameraAndScreenActive()) {\n-\t\t\t\tthis.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publishVideo);\n-\t\t\t\tthis.participantService.disableWebcamStream();\n-\t\t\t\tthis.openviduService.unpublish(this.participantService.getMyCameraPublisher());\n-\t\t\t\tthis.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publishAudio);\n-\t\t\t\treturn;\n-\t\t\t}\n-\t\t\t// Enabling webcam\n-\t\t\tif (this.participantService.isOnlyMyScreenActive()) {\n-\t\t\t\tconst hasAudio = this.participantService.hasScreenAudioActive();\n-\n-\t\t\t\tif (!this.openviduService.isWebcamSessionConnected()) {\n-\t\t\t\t\tawait this.openviduService.connectSession(this.openviduService.getWebcamSession(), this.tokenService.getWebcamToken());\n-\t\t\t\t}\n-\t\t\t\tawait this.openviduService.publish(this.participantService.getMyCameraPublisher());\n-\t\t\t\tthis.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), false);\n-\t\t\t\tthis.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), hasAudio);\n-\t\t\t\tthis.participantService.enableWebcamStream();\n-\t\t\t}\n-\t\t\t// Muting/unmuting webcam\n-\t\t\tthis.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publishVideo);\n+\t\t\tawait this.openviduService.muteVideo(publishVideo);\n \t\t} catch (error) {\n \t\t\tthis.log.e('There was an error toggling camera:', error.code, error.message);\n-\t\t\tthis.actionService.openDialog('There was an error toggling camera:', error?.error || error?.message);\n+\t\t\tthis.actionService.openDialog('There was an error toggling camera', error?.error || error?.message);\n \t\t}\n \t}\n \n@@ -343,76 +317,12 @@ export class ToolbarComponent implements OnInit, OnDestroy {\n \t\tthis.onScreenshareButtonClicked.emit();\n \n \t\ttry {\n-\t\t\t// Disabling screenShare\n-\t\t\tif (this.participantService.haveICameraAndScreenActive()) {\n-\t\t\t\tthis.participantService.disableScreenStream();\n-\t\t\t\tthis.openviduService.unpublish(this.participantService.getMyScreenPublisher());\n-\t\t\t\treturn;\n-\t\t\t}\n-\n-\t\t\t// Enabling screenShare\n-\t\t\tif (this.participantService.isOnlyMyCameraActive()) {\n-\t\t\t\tconst willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive();\n-\t\t\t\tconst hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.participantService.hasCameraAudioActive();\n-\t\t\t\tconst properties: PublisherProperties = {\n-\t\t\t\t\tvideoSource: ScreenType.SCREEN,\n-\t\t\t\t\taudioSource: this.hasAudioDevices ? undefined : null,\n-\t\t\t\t\tpublishVideo: true,\n-\t\t\t\t\tpublishAudio: hasAudio,\n-\t\t\t\t\tmirror: false\n-\t\t\t\t};\n-\t\t\t\tconst screenPublisher = await this.openviduService.initPublisher(undefined, properties);\n-\n-\t\t\t\tscreenPublisher.once('accessAllowed', async (event) => {\n-\t\t\t\t\t// Listen to event fired when native stop button is clicked\n-\t\t\t\t\tscreenPublisher.stream\n-\t\t\t\t\t\t.getMediaStream()\n-\t\t\t\t\t\t.getVideoTracks()[0]\n-\t\t\t\t\t\t.addEventListener('ended', () => {\n-\t\t\t\t\t\t\tthis.log.d('Clicked native stop button. Stopping screen sharing');\n-\t\t\t\t\t\t\tthis.toggleScreenShare();\n-\t\t\t\t\t\t});\n-\t\t\t\t\tthis.log.d('ACCESS ALOWED screenPublisher');\n-\t\t\t\t\tthis.participantService.activeMyScreenShare(screenPublisher);\n-\n-\t\t\t\t\tif (!this.openviduService.isScreenSessionConnected()) {\n-\t\t\t\t\t\tawait this.openviduService.connectSession(\n-\t\t\t\t\t\t\tthis.openviduService.getScreenSession(),\n-\t\t\t\t\t\t\tthis.tokenService.getScreenToken()\n-\t\t\t\t\t\t);\n-\t\t\t\t\t}\n-\t\t\t\t\tawait this.openviduService.publish(this.participantService.getMyScreenPublisher());\n-\t\t\t\t\t// this.openviduService.sendNicknameSignal();\n-\t\t\t\t\tif (!this.participantService.hasCameraVideoActive()) {\n-\t\t\t\t\t\t// Disabling webcam\n-\t\t\t\t\t\tthis.participantService.disableWebcamStream();\n-\t\t\t\t\t\tthis.openviduService.unpublish(this.participantService.getMyCameraPublisher());\n-\t\t\t\t\t}\n-\t\t\t\t});\n-\n-\t\t\t\tscreenPublisher.once('accessDenied', (error: any) => {\n-\t\t\t\t\tthis.log.e(error);\n-\t\t\t\t\tif (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {\n-\t\t\t\t\t\tthis.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing');\n-\t\t\t\t\t}\n-\t\t\t\t});\n-\t\t\t\treturn;\n-\t\t\t}\n-\n-\t\t\t// Disabling screnShare and enabling webcam\n-\t\t\tconst hasAudio = this.participantService.hasScreenAudioActive();\n-\t\t\tif (!this.openviduService.isWebcamSessionConnected()) {\n-\t\t\t\tawait this.openviduService.connectSession(this.openviduService.getWebcamSession(), this.tokenService.getWebcamToken());\n-\t\t\t}\n-\t\t\tawait this.openviduService.publish(this.participantService.getMyCameraPublisher());\n-\t\t\tthis.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), false);\n-\t\t\tthis.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), hasAudio);\n-\t\t\tthis.participantService.enableWebcamStream();\n-\t\t\tthis.participantService.disableScreenStream();\n-\t\t\tthis.openviduService.unpublish(this.participantService.getMyScreenPublisher());\n+\t\t\tawait this.openviduService.toggleScreenshare();\n \t\t} catch (error) {\n-\t\t\tthis.log.e('There was an error toggling screen share:', error.code, error.message);\n-\t\t\tthis.actionService.openDialog('There was an error toggling screen share:', error?.error || error?.message);\n+\t\t\tthis.log.e('There was an error toggling screen share', error.code, error.message);\n+\t\t\tif (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {\n+\t\t\t\tthis.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing');\n+\t\t\t}\n \t\t}\n \t}\n \ndiff --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\nindex 533a3b75..a8f95a74 100644\n--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts\n+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/config/openvidu-angular.config.ts\n@@ -3,8 +3,6 @@ import { ParticipantProperties, StreamModel } from '../models/participant.model'\n export interface OpenViduAngularConfig {\n \tproduction?: boolean,\n \tparticipantFactory?: ParticipantFactoryFunction,\n-\twebcomponent?: boolean\n-\n }\n \n export type ParticipantFactoryFunction = (props: ParticipantProperties, streamModel: StreamModel) => any;\n\\ No newline at end of file\ndiff --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\nindex 2b9ee3f1..c6dca29d 100644\n--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts\n+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/openvidu/openvidu.service.ts\n@@ -1,14 +1,5 @@\n import { Injectable } from '@angular/core';\n-import {\n-\tConnection,\n-\tOpenVidu,\n-\tOpenViduError,\n-\tOpenViduErrorName,\n-\tPublisher,\n-\tPublisherProperties,\n-\tSession,\n-\tSignalOptions\n-} from 'openvidu-browser';\n+import { Connection, OpenVidu, Publisher, PublisherProperties, Session, SignalOptions } from 'openvidu-browser';\n \n import { LoggerService } from '../logger/logger.service';\n \n@@ -18,8 +9,9 @@ import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.\n import { PlatformService } from '../platform/platform.service';\n import { DeviceService } from '../device/device.service';\n import { CameraType } from '../../models/device.model';\n-import { VideoType } from '../../models/video-type.model';\n+import { ScreenType, VideoType } from '../../models/video-type.model';\n import { ParticipantService } from '../participant/participant.service';\n+import { TokenService } from '../token/token.service';\n \n @Injectable({\n \tprovidedIn: 'root'\n@@ -41,7 +33,8 @@ export class OpenViduService {\n \t\tprotected platformService: PlatformService,\n \t\tprotected loggerSrv: LoggerService,\n \t\tprivate participantService: ParticipantService,\n-\t\tprotected deviceService: DeviceService\n+\t\tprotected deviceService: DeviceService,\n+\t\tprotected tokenService: TokenService\n \t) {\n \t\tthis.log = this.loggerSrv.get('OpenViduService');\n \t}\n@@ -51,6 +44,11 @@ export class OpenViduService {\n \t */\n \tinitialize() {\n \t\tthis.OV = new OpenVidu();\n+\t\tthis.OV.setAdvancedConfiguration({\n+\t\t\tpublisherSpeakingEventsOptions: {\n+\t\t\t\tinterval: 50\n+\t\t\t}\n+\t\t});\n \t\tif (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode();\n \t\tthis.webcamSession = this.OV.initSession();\n \n@@ -163,8 +161,6 @@ export class OpenViduService {\n \t\t\t// audioSource = undefined;\n \t\t}\n \n-\t\t// const videoSource = publishVideo ? this.deviceService.getCameraSelected().device : false;\n-\t\t// const audioSource = publishAudio ? this.deviceService.getMicrophoneSelected().device : false;\n \t\tconst mirror = this.deviceService.getCameraSelected() && this.deviceService.getCameraSelected().type === CameraType.FRONT;\n \t\tconst properties: PublisherProperties = {\n \t\t\tvideoSource,\n@@ -213,10 +209,10 @@ export class OpenViduService {\n \t/**\n \t * @internal\n \t */\n-\tunpublish(publisher: Publisher): void {\n+\tprivate unpublish(publisher: Publisher): void {\n \t\tif (!!publisher) {\n \t\t\tif (publisher === this.participantService.getMyCameraPublisher()) {\n-\t\t\t\tthis.publishAudio(this.participantService.getMyScreenPublisher(), this.participantService.hasCameraAudioActive());\n+\t\t\t\tthis.publishAudioAux(this.participantService.getMyScreenPublisher(), this.participantService.hasCameraAudioActive());\n \t\t\t\tthis.webcamSession.unpublish(publisher);\n \t\t\t} else if (publisher === this.participantService.getMyScreenPublisher()) {\n \t\t\t\tthis.screenSession.unpublish(publisher);\n@@ -224,20 +220,127 @@ export class OpenViduService {\n \t\t}\n \t}\n \n+\tasync muteVideo(mute: boolean): Promise<void> {\n+\t\tconst publishAudio = this.participantService.hasCameraAudioActive();\n+\t\t// const publishVideo = !this.participantService.hasCameraVideoActive();\n+\n+\t\t// Disabling webcam\n+\t\tif (this.participantService.haveICameraAndScreenActive()) {\n+\t\t\tthis.publishVideoAux(this.participantService.getMyCameraPublisher(), mute);\n+\t\t\tthis.participantService.disableWebcamStream();\n+\t\t\tthis.unpublish(this.participantService.getMyCameraPublisher());\n+\t\t\tthis.publishAudioAux(this.participantService.getMyScreenPublisher(), publishAudio);\n+\t\t} else if (this.participantService.isOnlyMyScreenActive()) {\n+\t\t\t// Enabling webcam\n+\t\t\tconst hasAudio = this.participantService.hasScreenAudioActive();\n+\t\t\tconsole.warn('Es audio activo?', hasAudio);\n+\t\t\tif (!this.isWebcamSessionConnected()) {\n+\t\t\t\t//TODO: should be the token in th participant?\n+\t\t\t\tawait this.connectSession(this.getWebcamSession(), this.tokenService.getWebcamToken());\n+\t\t\t}\n+\t\t\tawait this.publish(this.participantService.getMyCameraPublisher());\n+\t\t\tthis.publishVideoAux(this.participantService.getMyCameraPublisher(), true);\n+\t\t\tthis.publishAudioAux(this.participantService.getMyScreenPublisher(), false);\n+\t\t\tthis.publishAudioAux(this.participantService.getMyCameraPublisher(), hasAudio);\n+\t\t\tthis.participantService.enableWebcamStream();\n+\t\t} else {\n+\t\t\t// Muting/unmuting webcam\n+\t\t\tthis.publishVideoAux(this.participantService.getMyCameraPublisher(), mute);\n+\t\t}\n+\t}\n+\n \t/**\n \t * @internal\n \t */\n-\tpublishVideo(publisher: Publisher, value: boolean): void {\n+\tprivate publishVideoAux(publisher: Publisher, value: boolean): void {\n \t\tif (!!publisher) {\n \t\t\tpublisher.publishVideo(value);\n \t\t\tthis.participantService.updateLocalParticipant();\n \t\t}\n \t}\n \n+\tasync muteAudio(value: boolean): Promise<void> {\n+\t\tif (this.participantService.isMyCameraActive()) {\n+\t\t\tif (this.participantService.isMyScreenActive() && this.participantService.hasScreenAudioActive()) {\n+\t\t\t\tthis.publishAudioAux(this.participantService.getMyScreenPublisher(), false);\n+\t\t\t}\n+\n+\t\t\tthis.publishAudioAux(this.participantService.getMyCameraPublisher(), value);\n+\t\t} else {\n+\t\t\tthis.publishAudioAux(this.participantService.getMyScreenPublisher(), value);\n+\t\t}\n+\t}\n+\n+\tasync toggleScreenshare() {\n+\t\tif (this.participantService.haveICameraAndScreenActive()) {\n+\t\t\t// Disabling screenShare\n+\t\t\tthis.participantService.disableScreenStream();\n+\t\t\tthis.unpublish(this.participantService.getMyScreenPublisher());\n+\t\t} else if (this.participantService.isOnlyMyCameraActive()) {\n+\t\t\t// I only have the camera published\n+\t\t\tconst hasAudioDevicesAvailable = this.deviceService.hasAudioDeviceAvailable();\n+\t\t\tconst willWebcamBePresent = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive();\n+\t\t\tconst hasAudio = willWebcamBePresent ? false : hasAudioDevicesAvailable && this.participantService.hasCameraAudioActive();\n+\n+\t\t\tconsole.warn('will be audio active', hasAudio);\n+\t\t\tconst properties: PublisherProperties = {\n+\t\t\t\tvideoSource: ScreenType.SCREEN,\n+\t\t\t\taudioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : null,\n+\t\t\t\tpublishVideo: true,\n+\t\t\t\tpublishAudio: hasAudio,\n+\t\t\t\tmirror: false\n+\t\t\t};\n+\t\t\tconst screenPublisher = await this.initPublisher(undefined, properties);\n+\n+\t\t\tscreenPublisher.once('accessAllowed', async () => {\n+\t\t\t\t// Listen to event fired when native stop button is clicked\n+\t\t\t\tscreenPublisher.stream\n+\t\t\t\t\t.getMediaStream()\n+\t\t\t\t\t.getVideoTracks()[0]\n+\t\t\t\t\t.addEventListener('ended', async () => {\n+\t\t\t\t\t\tthis.log.d('Clicked native stop button. Stopping screen sharing');\n+\t\t\t\t\t\tawait this.toggleScreenshare();\n+\t\t\t\t\t});\n+\n+\t\t\t\t// Enabling screenShare\n+\t\t\t\tthis.participantService.activeMyScreenShare(screenPublisher);\n+\n+\t\t\t\tif (!this.isScreenSessionConnected()) {\n+\t\t\t\t\tawait this.connectSession(this.getScreenSession(), this.tokenService.getScreenToken());\n+\t\t\t\t}\n+\t\t\t\tawait this.publish(this.participantService.getMyScreenPublisher());\n+\t\t\t\tif (!this.participantService.hasCameraVideoActive()) {\n+\t\t\t\t\t// Disabling webcam\n+\t\t\t\t\tthis.participantService.disableWebcamStream();\n+\t\t\t\t\tthis.unpublish(this.participantService.getMyCameraPublisher());\n+\t\t\t\t}\n+\t\t\t});\n+\n+\t\t\tscreenPublisher.once('accessDenied', (error: any) => {\n+\t\t\t\treturn Promise.reject(error);\n+\t\t\t});\n+\t\t} else {\n+\t\t\t// I only have my screenshare active and I have no camera or it is muted\n+\t\t\tconst hasAudio = this.participantService.hasScreenAudioActive();\n+\n+\t\t\t// Enable webcam\n+\t\t\tif (!this.isWebcamSessionConnected()) {\n+\t\t\t\tawait this.connectSession(this.getWebcamSession(), this.tokenService.getWebcamToken());\n+\t\t\t}\n+\t\t\tawait this.publish(this.participantService.getMyCameraPublisher());\n+\t\t\tthis.publishAudioAux(this.participantService.getMyCameraPublisher(), hasAudio);\n+\t\t\tthis.participantService.enableWebcamStream();\n+\n+\t\t\t// Disabling screenshare\n+\t\t\tthis.participantService.disableScreenStream();\n+\t\t\tthis.unpublish(this.participantService.getMyScreenPublisher());\n+\t\t}\n+\t}\n+\n \t/**\n \t * @internal\n \t */\n-\tpublishAudio(publisher: Publisher, value: boolean): void {\n+\tprivate publishAudioAux(publisher: Publisher, value: boolean): void {\n \t\tif (!!publisher) {\n \t\t\tpublisher.publishAudio(value);\n \t\t\tthis.participantService.updateLocalParticipant();\n@@ -368,32 +471,33 @@ export class OpenViduService {\n \t\t}\n \t}\n \n-\tprivate async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {\n-\t\tlet mediaStream: MediaStream;\n-\t\tconst isFirefoxPlatform = this.platformService.isFirefox();\n-\t\tconst isReplacingAudio = !!pp.audioSource;\n-\t\tconst isReplacingVideo = !!pp.videoSource;\n-\n-\t\ttry {\n-\t\t\tmediaStream = await this.OV.getUserMedia(pp);\n-\t\t} catch (error) {\n-\t\t\tif ((<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) {\n-\t\t\t\tif (isFirefoxPlatform) {\n-\t\t\t\t\tthis.log.w('The device requested is not available. Restoring the older one');\n-\t\t\t\t\t// The track requested is not available so we are getting the old tracks ids for recovering the track\n-\t\t\t\t\tif (isReplacingVideo) {\n-\t\t\t\t\t\tpp.videoSource = this.deviceService.getCameraSelected().device;\n-\t\t\t\t\t} else if (isReplacingAudio) {\n-\t\t\t\t\t\tpp.audioSource = this.deviceService.getMicrophoneSelected().device;\n-\t\t\t\t\t}\n-\t\t\t\t\tmediaStream = await this.OV.getUserMedia(pp);\n-\t\t\t\t\t// TODO show error alert informing that the new device is not available\n-\t\t\t\t}\n-\t\t\t}\n-\t\t} finally {\n-\t\t\treturn mediaStream;\n-\t\t}\n-\t}\n+\t//TODO: Uncomment this section when replaceTrack issue is fixed\n+\t// private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {\n+\t// \tlet mediaStream: MediaStream;\n+\t// \tconst isFirefoxPlatform = this.platformService.isFirefox();\n+\t// \tconst isReplacingAudio = !!pp.audioSource;\n+\t// \tconst isReplacingVideo = !!pp.videoSource;\n+\n+\t// \ttry {\n+\t// \t\tmediaStream = await this.OV.getUserMedia(pp);\n+\t// \t} catch (error) {\n+\t// \t\tif ((<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) {\n+\t// \t\t\tif (isFirefoxPlatform) {\n+\t// \t\t\t\tthis.log.w('The device requested is not available. Restoring the older one');\n+\t// \t\t\t\t// The track requested is not available so we are getting the old tracks ids for recovering the track\n+\t// \t\t\t\tif (isReplacingVideo) {\n+\t// \t\t\t\t\tpp.videoSource = this.deviceService.getCameraSelected().device;\n+\t// \t\t\t\t} else if (isReplacingAudio) {\n+\t// \t\t\t\t\tpp.audioSource = this.deviceService.getMicrophoneSelected().device;\n+\t// \t\t\t\t}\n+\t// \t\t\t\tmediaStream = await this.OV.getUserMedia(pp);\n+\t// \t\t\t\t// TODO show error alert informing that the new device is not available\n+\t// \t\t\t}\n+\t// \t\t}\n+\t// \t} finally {\n+\t// \t\treturn mediaStream;\n+\t// \t}\n+\t// }\n \n \t/**\n \t * @internal\ndiff --git a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts\nindex d26e489c..df76a2f0 100644\n--- a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts\n+++ b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts\n@@ -41,6 +41,7 @@ export * from './lib/config/openvidu-angular.config';\n export * from './lib/models/logger.model';\n export * from './lib/models/video-type.model';\n export * from './lib/models/notification-options.model';\n+export * from './lib/models/token.model';\n \n // Pipes\n export * from './lib/pipes/participant.pipe';\n", 'commit_subject': 'openvidu-components: Moved component logic to openvidu service', 'repo_name': 'OpenVidu/openvidu', 'committer': {'name': 'csantosm', 'email': '5e677ea80f533f5cc346502f375a4c8eec87a568@gmail.com', 'time_sec': '1648722324', 'tz_offset': '120', 'date': {'seconds': '1648722324'}}, 'commit_tree': 'b23eb8041dcbef51404ea217f967c6e62c39cebf', 'commit_message': 'openvidu-components: Moved component logic to openvidu service\n\nMoved toggle screen, toggle video and toggle audio logic from toolbar and prejoin component to openvidu service with the aim of avoiding code duplications and being able to provide a powerful method to the components user', 'language_name': 'Shell', 'license': 'apache-2.0', 'hunks': "@@ -41,6 +41,7 @@ export * from './lib/config/openvidu-angular.config';\n export * from './lib/models/logger.model';\n export * from './lib/models/video-type.model';\n export * from './lib/models/notification-options.model';\n+export * from './lib/models/token.model';\n \n // Pipes\n export * from './lib/pipes/participant.pipe';\n", 'addition_count': 1, 'deletion_count': 0, 'src_file': 'a/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts', 'tgt_file': 'b/openvidu-components-angular/projects/openvidu-angular/src/public-api.ts', 'file_extension': '.ts', 'before_file': "/*\n * Public API Surface of openvidu-components-angular\n */\n\nexport * from './lib/openvidu-angular.module';\n\n// Services\nexport * from './lib/services/openvidu/openvidu.service';\nexport * from './lib/services/participant/participant.service';\nexport * from './lib/services/chat/chat.service';\nexport * from './lib/services/action/action.service';\nexport * from './lib/services/layout/layout.service';\nexport * from './lib/services/panel/panel.service';\nexport * from './lib/services/recording/recording.service';\n\n// Components\nexport * from './lib/components/videoconference/videoconference.component';\nexport * from './lib/components/toolbar/toolbar.component';\nexport * from './lib/components/panel/panel.component';\nexport * from './lib/components/panel/activities-panel/activities-panel.component';\nexport * from './lib/components/panel/chat-panel/chat-panel.component';\nexport * from './lib/components/panel/participants-panel/participants-panel/participants-panel.component';\nexport * from './lib/components/panel/participants-panel/participant-panel-item/participant-panel-item.component';\nexport * from './lib/components/layout/layout.component';\nexport * from './lib/components/stream/stream.component';\nexport * from './lib/admin/dashboard/dashboard.component';\nexport * from './lib/admin/login/login.component';\n\n// Models\nexport * from './lib/models/participant.model';\nexport * from './lib/config/openvidu-angular.config';\nexport * from './lib/models/video-type.model';\nexport * from './lib/models/token.model';\nexport * from './lib/models/signal.model';\nexport * from './lib/models/panel.model';\nexport * from './lib/models/recording.model';\n\n// Pipes\nexport * from './lib/pipes/participant.pipe';\nexport * from './lib/pipes/recording.pipe';\nexport * from './lib/models/logger.model';\nexport * from './lib/models/video-type.model';\nexport * from './lib/models/notification-options.model';\n\n// Pipes\nexport * from './lib/pipes/participant.pipe';\nexport * from './lib/directives/api/toolbar.directive';\nexport * from './lib/directives/api/stream.directive';\nexport * from './lib/directives/api/videoconference.directive';\nexport * from './lib/directives/api/participant-panel-item.directive';\nexport * from './lib/directives/api/activities-panel.directive';\nexport * from './lib/directives/api/recording-activity.directive';\nexport * from './lib/directives/api/admin.directive';\n", 'message': 'openvidu-components: Moved component logic to openvidu service\n\nMoved toggle screen, toggle video and toggle audio logic from toolbar and prejoin component to openvidu service with the aim of avoiding code duplications and being able to provide a powerful method to the components user', 'author_name': 'csantosm', 'lang': 'ts'}