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
pull/713/head
csantosm 2022-03-31 12:25:02 +02:00
parent fccde40641
commit 98fbe060a3
5 changed files with 177 additions and 234 deletions

View File

@ -1,11 +1,9 @@
import { Component, HostListener, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core'; import { Component, HostListener, OnDestroy, OnInit, Output, EventEmitter } from '@angular/core';
import { Publisher, PublisherProperties } from 'openvidu-browser'; import { PublisherProperties } from 'openvidu-browser';
import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/OpenViduError';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { CustomDevice } from '../../models/device.model'; import { CustomDevice } from '../../models/device.model';
import { ILogger } from '../../models/logger.model'; import { ILogger } from '../../models/logger.model';
import { ParticipantAbstractModel, ParticipantProperties } from '../../models/participant.model'; import { ParticipantAbstractModel } from '../../models/participant.model';
import { ActionService } from '../../services/action/action.service';
import { DeviceService } from '../../services/device/device.service'; import { DeviceService } from '../../services/device/device.service';
import { LayoutService } from '../../services/layout/layout.service'; import { LayoutService } from '../../services/layout/layout.service';
import { LoggerService } from '../../services/logger/logger.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 }; const pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror };
await this.openviduService.republishTrack(pp); await this.openviduService.republishTrack(pp);
this.cameraSelected = videoSource; this.deviceSrv.setCameraSelected(videoSource);
this.deviceSrv.setCameraSelected(this.cameraSelected); this.cameraSelected = this.deviceSrv.getCameraSelected();
}
if (this.isVideoMuted) {
// Publish Webcam video
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);
this.isVideoMuted = false;
} }
} }
async onMicrophoneSelected(event: any) { async onMicrophoneSelected(event: any) {
const audioSource = event?.value; const audioSource = event?.value;
// Is New deviceId different than older?
if (this.deviceSrv.needUpdateAudioTrack(audioSource)) { if (this.deviceSrv.needUpdateAudioTrack(audioSource)) {
//TODO: Uncomment this when replaceTrack issue is fixed //TODO: Uncomment this when replaceTrack issue is fixed
// const pp: PublisherProperties = { audioSource, videoSource: false }; // 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 }; const pp: PublisherProperties = { videoSource: this.cameraSelected.device, audioSource, mirror };
await this.openviduService.republishTrack(pp); await this.openviduService.republishTrack(pp);
this.microphoneSelected = audioSource; this.deviceSrv.setMicSelected(audioSource);
this.deviceSrv.setMicSelected(this.microphoneSelected); this.microphoneSelected = this.deviceSrv.getMicrophoneSelected();
}
if (this.isAudioMuted) {
// Enable microphone
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), true);
this.isAudioMuted = true;
} }
} }
toggleCam() { async toggleCam() {
const publish = this.isVideoMuted; const publish = this.isVideoMuted;
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publish); await this.openviduService.muteVideo(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();
}
this.isVideoMuted = !this.isVideoMuted; this.isVideoMuted = !this.isVideoMuted;
this.storageSrv.setVideoMuted(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() { toggleMic() {
const publish = this.isAudioMuted; const publish = this.isAudioMuted;
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), publish); this.openviduService.muteAudio(publish);
this.isAudioMuted = !this.isAudioMuted; this.isAudioMuted = !this.isAudioMuted;
this.storageSrv.setAudioMuted(this.isAudioMuted); this.storageSrv.setAudioMuted(this.isAudioMuted);
} }

View File

@ -19,8 +19,7 @@ import { DocumentService } from '../../services/document/document.service';
import { OpenViduService } from '../../services/openvidu/openvidu.service'; import { OpenViduService } from '../../services/openvidu/openvidu.service';
import { LoggerService } from '../../services/logger/logger.service'; import { LoggerService } from '../../services/logger/logger.service';
import { ILogger } from '../../models/logger.model'; import { ILogger } from '../../models/logger.model';
import { ScreenType } from '../../models/video-type.model'; import { Session } from 'openvidu-browser';
import { PublisherProperties, Session } from 'openvidu-browser';
import { ActionService } from '../../services/action/action.service'; import { ActionService } from '../../services/action/action.service';
import { DeviceService } from '../../services/device/device.service'; import { DeviceService } from '../../services/device/device.service';
import { ChatMessage } from '../../models/chat.model'; import { ChatMessage } from '../../models/chat.model';
@ -286,16 +285,13 @@ export class ToolbarComponent implements OnInit, OnDestroy {
/** /**
* @ignore * @ignore
*/ */
toggleMicrophone() { async toggleMicrophone() {
this.onMicrophoneButtonClicked.emit(); this.onMicrophoneButtonClicked.emit();
try {
if (this.participantService.isMyCameraActive()) { await this.openviduService.muteAudio(!this.isAudioActive);
this.openviduService.publishAudio( } catch (error) {
this.participantService.getMyCameraPublisher(), this.log.e('There was an error toggling microphone:', error.code, error.message);
!this.participantService.hasCameraAudioActive() this.actionService.openDialog('There was an error toggling camera', error?.error || error?.message);
);
} else {
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), !this.participantService.hasScreenAudioActive());
} }
} }
@ -307,32 +303,10 @@ export class ToolbarComponent implements OnInit, OnDestroy {
try { try {
const publishVideo = !this.participantService.hasCameraVideoActive(); const publishVideo = !this.participantService.hasCameraVideoActive();
const publishAudio = this.participantService.hasCameraAudioActive(); await this.openviduService.muteVideo(publishVideo);
// 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);
} catch (error) { } catch (error) {
this.log.e('There was an error toggling camera:', error.code, error.message); 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(); this.onScreenshareButtonClicked.emit();
try { try {
// Disabling screenShare await this.openviduService.toggleScreenshare();
if (this.participantService.haveICameraAndScreenActive()) { } catch (error) {
this.participantService.disableScreenStream(); this.log.e('There was an error toggling screen share', error.code, error.message);
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') { if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {
this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing'); 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());
} 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);
} }
} }

View File

@ -3,8 +3,6 @@ import { ParticipantProperties, StreamModel } from '../models/participant.model'
export interface OpenViduAngularConfig { export interface OpenViduAngularConfig {
production?: boolean, production?: boolean,
participantFactory?: ParticipantFactoryFunction, participantFactory?: ParticipantFactoryFunction,
webcomponent?: boolean
} }
export type ParticipantFactoryFunction = (props: ParticipantProperties, streamModel: StreamModel) => any; export type ParticipantFactoryFunction = (props: ParticipantProperties, streamModel: StreamModel) => any;

View File

@ -1,14 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { import { Connection, OpenVidu, Publisher, PublisherProperties, Session, SignalOptions } from 'openvidu-browser';
Connection,
OpenVidu,
OpenViduError,
OpenViduErrorName,
Publisher,
PublisherProperties,
Session,
SignalOptions
} from 'openvidu-browser';
import { LoggerService } from '../logger/logger.service'; import { LoggerService } from '../logger/logger.service';
@ -18,8 +9,9 @@ import { OpenViduAngularConfigService } from '../config/openvidu-angular.config.
import { PlatformService } from '../platform/platform.service'; import { PlatformService } from '../platform/platform.service';
import { DeviceService } from '../device/device.service'; import { DeviceService } from '../device/device.service';
import { CameraType } from '../../models/device.model'; 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 { ParticipantService } from '../participant/participant.service';
import { TokenService } from '../token/token.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -41,7 +33,8 @@ export class OpenViduService {
protected platformService: PlatformService, protected platformService: PlatformService,
protected loggerSrv: LoggerService, protected loggerSrv: LoggerService,
private participantService: ParticipantService, private participantService: ParticipantService,
protected deviceService: DeviceService protected deviceService: DeviceService,
protected tokenService: TokenService
) { ) {
this.log = this.loggerSrv.get('OpenViduService'); this.log = this.loggerSrv.get('OpenViduService');
} }
@ -51,6 +44,11 @@ export class OpenViduService {
*/ */
initialize() { initialize() {
this.OV = new OpenVidu(); this.OV = new OpenVidu();
this.OV.setAdvancedConfiguration({
publisherSpeakingEventsOptions: {
interval: 50
}
});
if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode(); if (this.openviduAngularConfigSrv.isProduction()) this.OV.enableProdMode();
this.webcamSession = this.OV.initSession(); this.webcamSession = this.OV.initSession();
@ -163,8 +161,6 @@ export class OpenViduService {
// audioSource = undefined; // 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 mirror = this.deviceService.getCameraSelected() && this.deviceService.getCameraSelected().type === CameraType.FRONT;
const properties: PublisherProperties = { const properties: PublisherProperties = {
videoSource, videoSource,
@ -213,10 +209,10 @@ export class OpenViduService {
/** /**
* @internal * @internal
*/ */
unpublish(publisher: Publisher): void { private unpublish(publisher: Publisher): void {
if (!!publisher) { if (!!publisher) {
if (publisher === this.participantService.getMyCameraPublisher()) { 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); this.webcamSession.unpublish(publisher);
} else if (publisher === this.participantService.getMyScreenPublisher()) { } else if (publisher === this.participantService.getMyScreenPublisher()) {
this.screenSession.unpublish(publisher); this.screenSession.unpublish(publisher);
@ -224,20 +220,127 @@ export class OpenViduService {
} }
} }
/** async muteVideo(mute: boolean): Promise<void> {
* @internal const publishAudio = this.participantService.hasCameraAudioActive();
*/ // const publishVideo = !this.participantService.hasCameraVideoActive();
publishVideo(publisher: Publisher, value: boolean): void {
if (!!publisher) { // Disabling webcam
publisher.publishVideo(value); if (this.participantService.haveICameraAndScreenActive()) {
this.participantService.updateLocalParticipant(); 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 * @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<void> {
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) { if (!!publisher) {
publisher.publishAudio(value); publisher.publishAudio(value);
this.participantService.updateLocalParticipant(); this.participantService.updateLocalParticipant();
@ -368,32 +471,33 @@ export class OpenViduService {
} }
} }
private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> { //TODO: Uncomment this section when replaceTrack issue is fixed
let mediaStream: MediaStream; // private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {
const isFirefoxPlatform = this.platformService.isFirefox(); // let mediaStream: MediaStream;
const isReplacingAudio = !!pp.audioSource; // const isFirefoxPlatform = this.platformService.isFirefox();
const isReplacingVideo = !!pp.videoSource; // const isReplacingAudio = !!pp.audioSource;
// const isReplacingVideo = !!pp.videoSource;
try { // try {
mediaStream = await this.OV.getUserMedia(pp); // mediaStream = await this.OV.getUserMedia(pp);
} catch (error) { // } catch (error) {
if ((<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) { // if ((<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED) {
if (isFirefoxPlatform) { // if (isFirefoxPlatform) {
this.log.w('The device requested is not available. Restoring the older one'); // 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 // // The track requested is not available so we are getting the old tracks ids for recovering the track
if (isReplacingVideo) { // if (isReplacingVideo) {
pp.videoSource = this.deviceService.getCameraSelected().device; // pp.videoSource = this.deviceService.getCameraSelected().device;
} else if (isReplacingAudio) { // } else if (isReplacingAudio) {
pp.audioSource = this.deviceService.getMicrophoneSelected().device; // pp.audioSource = this.deviceService.getMicrophoneSelected().device;
} // }
mediaStream = await this.OV.getUserMedia(pp); // mediaStream = await this.OV.getUserMedia(pp);
// TODO show error alert informing that the new device is not available // // TODO show error alert informing that the new device is not available
} // }
} // }
} finally { // } finally {
return mediaStream; // return mediaStream;
} // }
} // }
/** /**
* @internal * @internal

View File

@ -41,6 +41,7 @@ export * from './lib/config/openvidu-angular.config';
export * from './lib/models/logger.model'; export * from './lib/models/logger.model';
export * from './lib/models/video-type.model'; export * from './lib/models/video-type.model';
export * from './lib/models/notification-options.model'; export * from './lib/models/notification-options.model';
export * from './lib/models/token.model';
// Pipes // Pipes
export * from './lib/pipes/participant.pipe'; export * from './lib/pipes/participant.pipe';