diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 5fd64fb3..27d11315 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -795,9 +795,12 @@ export class Session implements EventDispatcher { } if (!!this.connection.stream) { - // Make Publisher object dispatch 'streamDestroyed' event (if there's a local stream) + // Dispose Publisher's local stream this.connection.stream.disposeWebRtcPeer(); - this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + if (this.connection.stream.isLocalStreamPublished) { + // Make Publisher object dispatch 'streamDestroyed' event if the Stream was published + this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + } } if (!this.connection.disposed) { diff --git a/openvidu-testapp/src/app/app.module.ts b/openvidu-testapp/src/app/app.module.ts index 4cad47d0..cd832bd8 100644 --- a/openvidu-testapp/src/app/app.module.ts +++ b/openvidu-testapp/src/app/app.module.ts @@ -14,14 +14,15 @@ import { VideoComponent } from './components/video/video.component'; import { OpenViduVideoComponent } from './components/video/ov-video.component'; import { ExtensionDialogComponent } from './components/dialogs/extension-dialog.component'; import { LocalRecordingDialogComponent } from './components/dialogs/local-recording-dialog.component'; +import { SessionPropertiesDialogComponent } from './components/dialogs/session-properties-dialog.component'; +import { SessionApiDialogComponent } from './components/dialogs/session-api-dialog.component'; +import { EventsDialogComponent } from './components/dialogs/events-dialog.component'; +import { PublisherPropertiesDialogComponent } from './components/dialogs/publisher-properties-dialog.component'; import { OpenviduRestService } from './services/openvidu-rest.service'; import { OpenviduParamsService } from './services/openvidu-params.service'; import { TestFeedService } from './services/test-feed.service'; import { MuteSubscribersService } from './services/mute-subscribers.service'; -import { SessionPropertiesDialogComponent } from './components/dialogs/session-properties-dialog.component'; -import { SessionApiDialogComponent } from './components/dialogs/session-api-dialog.component'; -import { EventsDialogComponent } from './components/dialogs/events-dialog.component'; @NgModule({ declarations: [ @@ -35,7 +36,8 @@ import { EventsDialogComponent } from './components/dialogs/events-dialog.compon SessionPropertiesDialogComponent, SessionApiDialogComponent, EventsDialogComponent, - LocalRecordingDialogComponent + LocalRecordingDialogComponent, + PublisherPropertiesDialogComponent ], imports: [ BrowserModule, @@ -56,7 +58,8 @@ import { EventsDialogComponent } from './components/dialogs/events-dialog.compon SessionPropertiesDialogComponent, SessionApiDialogComponent, EventsDialogComponent, - LocalRecordingDialogComponent + LocalRecordingDialogComponent, + PublisherPropertiesDialogComponent ], bootstrap: [AppComponent] }) diff --git a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.css new file mode 100644 index 00000000..de985c76 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.css @@ -0,0 +1,31 @@ +mat-chip { + margin: 0 0 5px 0 !important; + height: 12px; + max-width: 180px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + cursor: pointer !important; +} + +mat-divider { + margin-top: 10px !important; + margin-bottom: 5px !important; +} + +button.device-btn { + height: 30px; + width: 30px; + line-height: 30px; +} + +button.device-btn mat-icon { + width: 20px; + height: 20px; + font-size: 20px; + line-height: 20px; +} + +div.mat-form-field-subscript-wrapper { + margin-top: 0 !important; +} \ No newline at end of file diff --git a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.html new file mode 100644 index 00000000..8ccb84b7 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.html @@ -0,0 +1,48 @@ +
+

Publisher properties

+ + Audio + + Video + + Publish audio + Publish video + Mirror + + + + + + + + {{audioDevice.label}} + + + + + + + + {{videoDevice.label}} + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.ts new file mode 100644 index 00000000..6783b4ae --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog.component.ts @@ -0,0 +1,105 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialog, MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; + +import { SessionProperties, MediaMode, RecordingMode, RecordingLayout } from 'openvidu-node-client'; +import { PublisherProperties, OpenVidu } from 'openvidu-browser'; + +@Component({ + selector: 'app-publisher-properties-dialog', + templateUrl: './publisher-properties-dialog.component.html', + styleUrls: ['./publisher-properties-dialog.component.css'], + providers: [ + { provide: MAT_CHECKBOX_CLICK_ACTION, useValue: 'noop' } + ] +}) +export class PublisherPropertiesDialogComponent { + + OV: OpenVidu; + publisherProperties: PublisherProperties; + initValue: PublisherProperties; + + audioSource; + videoSource; + + audioSourceAux; + videoSourceAux; + + audioDevices = []; + videoDevices = []; + + private mediaMode = MediaMode; + private recordingMode = RecordingMode; + private defaultRecordingLayout = RecordingLayout; + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: PublisherProperties) { + this.publisherProperties = data; + this.OV = new OpenVidu(); + this.initValue = Object.assign({}, this.publisherProperties); + this.audioSource = typeof this.publisherProperties.audioSource === 'string' ? this.publisherProperties.audioSource : undefined; + this.videoSource = typeof this.publisherProperties.videoSource === 'string' ? this.publisherProperties.videoSource : undefined; + } + + toggleAudio(): void { + if (this.publisherProperties.audioSource === false) { + this.publisherProperties.audioSource = this.audioSource; + this.audioSource = this.audioSourceAux; + } else { + this.audioSourceAux = this.audioSource; + this.audioSource = undefined; + this.publisherProperties.audioSource = false; + } + } + + toggleVideo(): void { + if (this.publisherProperties.videoSource === false) { + this.publisherProperties.videoSource = this.videoSource; + this.videoSource = this.videoSourceAux; + } else { + this.videoSourceAux = this.videoSource; + this.videoSource = undefined; + this.publisherProperties.videoSource = false; + } + } + + setCloseValue(): PublisherProperties { + if (typeof this.audioSource === 'string') { + if (!!this.audioSource) { + this.publisherProperties.audioSource = this.audioSource; + } else { + this.publisherProperties.audioSource = undefined; + } + } + if (typeof this.videoSource === 'string') { + if (!!this.videoSource) { + this.publisherProperties.videoSource = this.videoSource; + } else { + this.publisherProperties.videoSource = undefined; + } + } + return this.publisherProperties; + } + + listAudioDevices() { + this.audioDevices = []; + this.OV.getDevices().then(devices => { + devices.forEach(device => { + if (device.kind === 'audioinput') { + this.audioDevices.push(device); + } + }); + }); + } + + listVideoDevices() { + this.videoDevices = []; + this.OV.getDevices().then(devices => { + devices.forEach(device => { + if (device.kind === 'videoinput') { + this.videoDevices.push(device); + } + }); + }); + } + +} diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog.component.ts index 7a5440bd..9c354c26 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog.component.ts @@ -48,9 +48,9 @@ export class SessionPropertiesDialogComponent { sessionProperties: SessionProperties; - private mediaMode = MediaMode; - private recordingMode = RecordingMode; - private defaultRecordingLayout = RecordingLayout; + mediaMode = MediaMode; + recordingMode = RecordingMode; + defaultRecordingLayout = RecordingLayout; constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: SessionProperties) { diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html index ef37cd93..a113ce61 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html @@ -33,10 +33,8 @@
- - Publish + + Publish
@@ -45,45 +43,45 @@

Send

- Audio - Video + Audio + Video

Enter active

- Audio - Video + Audio + Video
- +
- Video + Video
- Screen + Screen
-
- -
@@ -129,9 +127,10 @@
- + - +
diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 5ede01b0..ec699abd 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -7,7 +7,8 @@ import { Subscription } from 'rxjs/Subscription'; import { OpenVidu, Session, Subscriber, Publisher, Stream, Connection, LocalRecorder, VideoInsertMode, StreamEvent, ConnectionEvent, - SessionDisconnectedEvent, SignalEvent, RecordingEvent, VideoElementEvent, PublisherSpeakingEvent, StreamManagerEvent, StreamManager + SessionDisconnectedEvent, SignalEvent, RecordingEvent, VideoElementEvent, + PublisherSpeakingEvent, StreamManagerEvent, StreamManager, PublisherProperties } from 'openvidu-browser'; import { OpenVidu as OpenViduAPI, @@ -17,21 +18,19 @@ import { RecordingMode, RecordingLayout } from 'openvidu-node-client'; -import { MatDialog, MatDialogRef } from '@angular/material'; +import { MatDialog, MatDialogRef, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; import { ExtensionDialogComponent } from '../dialogs/extension-dialog.component'; import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog.component'; import { TestFeedService } from '../../services/test-feed.service'; -import { MuteSubscribersService } from '../../services/mute-subscribers.service'; import { EventsDialogComponent } from '../dialogs/events-dialog.component'; import { SessionPropertiesDialogComponent } from '../dialogs/session-properties-dialog.component'; import { SessionApiDialogComponent } from '../dialogs/session-api-dialog.component'; +import { PublisherPropertiesDialogComponent } from '../dialogs/publisher-properties-dialog.component'; export interface SessionConf { subscribeTo: boolean; publishTo: boolean; - sendAudio: boolean; - sendVideo: boolean; startSession: boolean; } @@ -43,7 +42,10 @@ export interface OpenViduEvent { @Component({ selector: 'app-openvidu-instance', templateUrl: './openvidu-instance.component.html', - styleUrls: ['./openvidu-instance.component.css'] + styleUrls: ['./openvidu-instance.component.css'], + providers: [ + { provide: MAT_CHECKBOX_CLICK_ACTION, useValue: 'noop' } + ] }) export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { @@ -66,30 +68,10 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { // Session options subscribeTo; publishTo; - sendAudio; - sendVideo; - activeAudio = true; - activeVideo = true; sendVideoRadio = true; subscribeToRemote = false; optionsVideo = 'video'; - // Form 'check' and 'disable' attributes - checkSubscribeTo = true; - checkPublishTo = true; - checkSendAudio = true; - checkSendVideo = true; - checkActiveAudio = true; - checkActiveVideo = true; - checkRadioVideo = true; - checkRadioScreen = false; - disablePublishTo = false; - disableSendAudio = false; - disableSendVideo = false; - disableActiveAudio = false; - disableActiveVideo = false; - disableRadioButtons = false; - // OpenVidu Browser objects OV: OpenVidu; session: Session; @@ -105,6 +87,18 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { customSessionId: '' }; + publisherProperties: PublisherProperties = { + audioSource: undefined, + videoSource: undefined, + frameRate: 30, + resolution: '640x480', + mirror: true, + publishAudio: true, + publishVideo: true + }; + + publisherPropertiesAux: PublisherProperties; + sessionEvents = { connectionCreated: true, connectionDestroyed: true, @@ -139,14 +133,11 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { ngOnInit() { this.subscribeTo = this.sessionConf.subscribeTo; this.publishTo = this.sessionConf.publishTo; - this.sendAudio = this.sessionConf.sendAudio; - this.sendVideo = this.sessionConf.sendVideo; - + this.publisherPropertiesAux = Object.assign({}, this.publisherProperties); if (!this.publishTo) { this.publishTo = !this.publishTo; this.togglePublishTo(); } - if (this.sessionConf.startSession) { this.joinSession(); } @@ -242,76 +233,49 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { togglePublishTo(): void { this.publishTo = !this.publishTo; - - this.sendAudio = this.publishTo; - this.sendVideo = this.publishTo; - this.activeAudio = this.publishTo; - this.activeVideo = this.publishTo; - - this.checkPublishTo = this.publishTo; - this.checkSendAudio = this.publishTo; - this.checkSendVideo = this.publishTo; - this.checkActiveAudio = this.publishTo; - this.checkActiveVideo = this.publishTo; - if (this.publishTo) { - this.checkRadioVideo = true; - this.optionsVideo = 'video'; + this.publisherProperties = this.publisherPropertiesAux; } else { - this.checkRadioVideo = false; - this.optionsVideo = ''; + this.publisherPropertiesAux = Object.assign({}, this.publisherProperties); + this.publisherProperties.publishAudio = false; + this.publisherProperties.publishVideo = false; + this.publisherProperties.audioSource = false; + this.publisherProperties.videoSource = false; } - this.disableSendAudio = !this.publishTo; - this.disableSendVideo = !this.publishTo; - this.disableActiveAudio = !this.publishTo; - this.disableActiveVideo = !this.publishTo; - this.disableRadioButtons = !this.publishTo; + if (this.publishTo) { + this.optionsVideo = 'video'; + } else { + this.optionsVideo = ''; + } this.subscribeToRemote = false; } toggleSendAudio(): void { - this.sendAudio = !this.sendAudio; - - this.activeAudio = this.sendAudio; - this.checkActiveAudio = this.sendAudio; - this.disableActiveAudio = !this.sendAudio; - - if (!this.sendAudio && !this.sendVideo && this.publishTo) { - this.togglePublishTo(); + if (this.publisherProperties.audioSource === false) { + this.publisherProperties.audioSource = this.publisherPropertiesAux.audioSource; + } else { + this.publisherPropertiesAux.audioSource = this.publisherProperties.audioSource; + this.publisherProperties.audioSource = false; } } toggleSendVideo(): void { - this.sendVideo = !this.sendVideo; - - this.activeVideo = this.sendVideo; - - this.checkActiveVideo = this.sendVideo; - this.checkRadioScreen = false; - if (this.sendVideo) { - this.checkRadioVideo = true; - this.optionsVideo = 'video'; + if (this.publisherProperties.videoSource === false) { + this.publisherProperties.videoSource = this.publisherPropertiesAux.videoSource; } else { - this.checkRadioVideo = false; - this.optionsVideo = ''; - } - - this.disableActiveVideo = !this.sendVideo; - this.disableRadioButtons = !this.sendVideo; - - if (!this.sendAudio && !this.sendVideo && this.publishTo) { - this.togglePublishTo(); + this.publisherPropertiesAux.videoSource = this.publisherProperties.videoSource; + this.publisherProperties.videoSource = false; } } toggleActiveAudio(): void { - this.activeAudio = !this.activeAudio; + this.publisherProperties.publishAudio = !this.publisherProperties.publishAudio; } toggleActiveVideo(): void { - this.activeVideo = !this.activeVideo; + this.publisherProperties.publishVideo = !this.publisherProperties.publishVideo; } sendMessage(): void { @@ -438,14 +402,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { syncInitPublisher() { this.publisher = this.OV.initPublisher( undefined, - { - audioSource: this.sendAudio ? undefined : false, - videoSource: this.sendVideo ? (this.optionsVideo === 'screen' ? 'screen' : undefined) : false, - publishAudio: this.activeAudio, - publishVideo: this.activeVideo, - resolution: '640x480', - frameRate: 30 - }, + this.publisherProperties, (err) => { if (err) { console.warn(err); @@ -467,46 +424,6 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.session.publish(this.publisher); } - asyncInitPublisher() { - this.OV.initPublisherAsync( - 'local-vid-' + this.session.connection.connectionId, - { - audioSource: this.sendAudio ? undefined : false, - videoSource: this.sendVideo ? (this.optionsVideo === 'screen' ? 'screen' : undefined) : false, - publishAudio: this.activeAudio, - publishVideo: this.activeVideo, - resolution: '640x480', - frameRate: 30, - insertMode: VideoInsertMode.APPEND - }) - .then(publisher => { - this.publisher = publisher; - if (this.subscribeToRemote) { - this.publisher.subscribeToRemote(); - } - this.session.publish(this.publisher) - .then(() => { - console.log(this.publisher); - }) - .catch(e => { - console.error(e); - }); - }) - .catch(err => { - if (err) { - console.error(err); - this.openviduError = err; - if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') { - this.dialog.open(ExtensionDialogComponent, { - data: { url: err.message }, - disableClose: true, - width: '250px' - }); - } - } - }); - } - syncSubscribe(session: Session, event) { this.subscribers.push(session.subscribe(event.stream, undefined)); } @@ -575,7 +492,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { openVidu: new OpenViduAPI(this.openviduUrl, this.openviduSecret), sessionId: !!this.session ? this.session.sessionId : this.sessionName }, - width: '280px' + width: '280px', + disableClose: true }); dialogRef.afterClosed().subscribe((result: string) => { @@ -630,6 +548,22 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { }); } + openPublisherPropertiesDialog() { + const dialogRef = this.dialog.open(PublisherPropertiesDialogComponent, { + data: this.publisherProperties, + width: '300px', + disableClose: true + }); + + dialogRef.afterClosed().subscribe((result: PublisherProperties) => { + if (!!result) { + this.publisherProperties = result; + this.optionsVideo = this.publisherProperties.videoSource === 'screen' ? 'screen' : 'video'; + } + document.getElementById('publisher-settings-btn-' + this.index).classList.remove('cdk-program-focused'); + }); + } + getToken(): Promise { const OV_NodeClient = new OpenViduAPI(this.openviduUrl, this.openviduSecret); if (!this.sessionProperties.customSessionId) { @@ -652,4 +586,19 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.subscribers[this.subscribers.indexOf(oldSubscriber)] = newSubscriber; } + updateOptionsVideo(change) { + if (change.value === 'screen') { + this.publisherPropertiesAux.videoSource = this.publisherProperties.videoSource; + this.publisherProperties.videoSource = 'screen'; + } else { + this.publisherProperties.videoSource = this.publisherPropertiesAux.videoSource; + } + } + + isVideo(): boolean { + return (this.publisherProperties.videoSource === undefined || + typeof this.publisherProperties.videoSource === 'string' && + this.publisherProperties.videoSource !== 'screen'); + } + } diff --git a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts index 8008ec21..0fa65c38 100644 --- a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts +++ b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts @@ -50,8 +50,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.users.push({ subscribeTo: true, publishTo: true, - sendAudio: true, - sendVideo: true, startSession: false }); } @@ -69,8 +67,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.users.push({ subscribeTo: true, publishTo: true, - sendAudio: true, - sendVideo: true, startSession: this.autoJoin }); } @@ -81,8 +77,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.users.push({ subscribeTo: true, publishTo: false, - sendAudio: false, - sendVideo: false, startSession: this.autoJoin }); } @@ -93,8 +87,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.users.push({ subscribeTo: false, publishTo: true, - sendAudio: true, - sendVideo: true, startSession: this.autoJoin }); } diff --git a/openvidu-testapp/src/app/components/video/video.component.html b/openvidu-testapp/src/app/components/video/video.component.html index 60d07f11..7ebcbe15 100644 --- a/openvidu-testapp/src/app/components/video/video.component.html +++ b/openvidu-testapp/src/app/components/video/video.component.html @@ -10,10 +10,10 @@ - - - -