mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser fix: streamDestroyed only triggered by Publisher after streamCreated
parent
37cdb9ccf0
commit
2f2a42c439
|
@ -795,10 +795,13 @@ export class Session implements EventDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!this.connection.stream) {
|
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.disposeWebRtcPeer();
|
||||||
|
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]);
|
this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.connection.disposed) {
|
if (!this.connection.disposed) {
|
||||||
// Make Session object dispatch 'sessionDisconnected' event (if it is not already disposed)
|
// Make Session object dispatch 'sessionDisconnected' event (if it is not already disposed)
|
||||||
|
|
|
@ -14,14 +14,15 @@ import { VideoComponent } from './components/video/video.component';
|
||||||
import { OpenViduVideoComponent } from './components/video/ov-video.component';
|
import { OpenViduVideoComponent } from './components/video/ov-video.component';
|
||||||
import { ExtensionDialogComponent } from './components/dialogs/extension-dialog.component';
|
import { ExtensionDialogComponent } from './components/dialogs/extension-dialog.component';
|
||||||
import { LocalRecordingDialogComponent } from './components/dialogs/local-recording-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 { OpenviduRestService } from './services/openvidu-rest.service';
|
||||||
import { OpenviduParamsService } from './services/openvidu-params.service';
|
import { OpenviduParamsService } from './services/openvidu-params.service';
|
||||||
import { TestFeedService } from './services/test-feed.service';
|
import { TestFeedService } from './services/test-feed.service';
|
||||||
import { MuteSubscribersService } from './services/mute-subscribers.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({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -35,7 +36,8 @@ import { EventsDialogComponent } from './components/dialogs/events-dialog.compon
|
||||||
SessionPropertiesDialogComponent,
|
SessionPropertiesDialogComponent,
|
||||||
SessionApiDialogComponent,
|
SessionApiDialogComponent,
|
||||||
EventsDialogComponent,
|
EventsDialogComponent,
|
||||||
LocalRecordingDialogComponent
|
LocalRecordingDialogComponent,
|
||||||
|
PublisherPropertiesDialogComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -56,7 +58,8 @@ import { EventsDialogComponent } from './components/dialogs/events-dialog.compon
|
||||||
SessionPropertiesDialogComponent,
|
SessionPropertiesDialogComponent,
|
||||||
SessionApiDialogComponent,
|
SessionApiDialogComponent,
|
||||||
EventsDialogComponent,
|
EventsDialogComponent,
|
||||||
LocalRecordingDialogComponent
|
LocalRecordingDialogComponent,
|
||||||
|
PublisherPropertiesDialogComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<div>
|
||||||
|
<h2 mat-dialog-title>Publisher properties</h2>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<mat-checkbox (click)="toggleAudio()" [checked]="publisherProperties.audioSource !== false">Audio
|
||||||
|
</mat-checkbox>
|
||||||
|
<mat-checkbox (click)="toggleVideo()" [checked]="publisherProperties.videoSource !== false">Video
|
||||||
|
</mat-checkbox>
|
||||||
|
<mat-checkbox [(ngModel)]="publisherProperties.publishAudio" (click)="publisherProperties.publishAudio = !publisherProperties.publishAudio">Publish audio</mat-checkbox>
|
||||||
|
<mat-checkbox [(ngModel)]="publisherProperties.publishVideo" (click)="publisherProperties.publishVideo = !publisherProperties.publishVideo">Publish video</mat-checkbox>
|
||||||
|
<mat-checkbox [(ngModel)]="publisherProperties.mirror" (click)="publisherProperties.mirror = !publisherProperties.mirror">Mirror</mat-checkbox>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Audio source" [(ngModel)]="audioSource" [disabled]="(publisherProperties.audioSource === false)">
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-icon-button class="device-btn" title="List audio devices" (click)="listAudioDevices()">
|
||||||
|
<mat-icon aria-label="List audio devices">add_circle</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button *ngIf="audioDevices.length > 0" mat-icon-button class="device-btn" title="Clear audio devices" (click)="audioDevices = []">
|
||||||
|
<mat-icon aria-label="Clear audio devices">clear</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-chip-list *ngIf="audioDevices.length > 0">
|
||||||
|
<mat-chip *ngFor="let audioDevice of audioDevices" (click)="audioSource=audioDevice.deviceId">{{audioDevice.label}}</mat-chip>
|
||||||
|
</mat-chip-list>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Video source" [(ngModel)]="videoSource" [disabled]="(publisherProperties.videoSource === false)">
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-icon-button class="device-btn" title="List video devices" (click)="listVideoDevices()">
|
||||||
|
<mat-icon aria-label="List video devices">add_circle</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button *ngIf="videoDevices.length > 0" mat-icon-button class="device-btn" title="Clear video devices" (click)="videoDevices = []">
|
||||||
|
<mat-icon aria-label="Clear video devices">clear</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-chip-list *ngIf="videoDevices.length > 0">
|
||||||
|
<mat-chip *ngFor="let videoDevice of videoDevices" (click)="videoSource=videoDevice.deviceId">{{videoDevice.label}}</mat-chip>
|
||||||
|
</mat-chip-list>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Resolution" [(ngModel)]="publisherProperties.resolution">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Framerate" [(ngModel)]="publisherProperties.frameRate" type="number">
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions>
|
||||||
|
<button mat-button [mat-dialog-close]="initValue">CANCEL</button>
|
||||||
|
<button mat-button [mat-dialog-close]="setCloseValue()">SAVE</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
|
</div>
|
|
@ -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<PublisherPropertiesDialogComponent>,
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,9 +48,9 @@ export class SessionPropertiesDialogComponent {
|
||||||
|
|
||||||
sessionProperties: SessionProperties;
|
sessionProperties: SessionProperties;
|
||||||
|
|
||||||
private mediaMode = MediaMode;
|
mediaMode = MediaMode;
|
||||||
private recordingMode = RecordingMode;
|
recordingMode = RecordingMode;
|
||||||
private defaultRecordingLayout = RecordingLayout;
|
defaultRecordingLayout = RecordingLayout;
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<SessionPropertiesDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<SessionPropertiesDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: SessionProperties) {
|
@Inject(MAT_DIALOG_DATA) public data: SessionProperties) {
|
||||||
|
|
|
@ -33,10 +33,8 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="join-btn" mat-button (click)="joinSession()" [disabled]="session">JOIN</button>
|
<button class="join-btn" mat-button (click)="joinSession()" [disabled]="session">JOIN</button>
|
||||||
<mat-checkbox class="subscribe-checkbox" name="subscribeTo" (change)="toggleSubscribeTo()" [checked]="subscribeTo && checkSubscribeTo"
|
<mat-checkbox class="subscribe-checkbox" name="subscribeTo" (click)="toggleSubscribeTo()" [checked]="subscribeTo" [disabled]="session">Subscribe</mat-checkbox>
|
||||||
[disabled]="session">Subscribe</mat-checkbox>
|
<mat-checkbox class="publish-checkbox" name="publishTo" (click)="togglePublishTo()" [checked]="publishTo" [disabled]="session">Publish</mat-checkbox>
|
||||||
<mat-checkbox class="publish-checkbox" name="publishTo" (change)="togglePublishTo()" [checked]="publishTo && checkPublishTo"
|
|
||||||
[disabled]="session || disablePublishTo">Publish</mat-checkbox>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inner-card" fxLayout="row" fxLayoutAlign="start start">
|
<div class="inner-card" fxLayout="row" fxLayoutAlign="start start">
|
||||||
|
@ -45,45 +43,45 @@
|
||||||
<div>
|
<div>
|
||||||
<h4>Send</h4>
|
<h4>Send</h4>
|
||||||
<div>
|
<div>
|
||||||
<mat-checkbox class="send-audio-checkbox" name="sendAudio" (change)="toggleSendAudio()" [checked]="sendAudio && checkSendAudio"
|
<mat-checkbox class="send-audio-checkbox" name="sendAudio" (click)="toggleSendAudio()" [checked]="publisherProperties.audioSource !== false"
|
||||||
[disabled]="session || disableSendAudio">Audio</mat-checkbox>
|
[disabled]="session || !publishTo">Audio</mat-checkbox>
|
||||||
<mat-checkbox class="send-video-checkbox" name="sendVideo" (change)="toggleSendVideo()" [checked]="sendVideo && checkSendVideo"
|
<mat-checkbox class="send-video-checkbox" name="sendVideo" (click)="toggleSendVideo()" [checked]="publisherProperties.videoSource !== false"
|
||||||
[disabled]="session || disableSendVideo">Video</mat-checkbox>
|
[disabled]="session || !publishTo">Video</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-top: 5px;">
|
<div style="padding-top: 5px;">
|
||||||
<h4>Enter active</h4>
|
<h4>Enter active</h4>
|
||||||
<div>
|
<div>
|
||||||
<mat-checkbox class="active-audio-checkbox" name="activeAudio" (change)="toggleActiveAudio()" [checked]="activeAudio && checkActiveAudio"
|
<mat-checkbox class="active-audio-checkbox" name="activeAudio" [(ngModel)]="publisherProperties.publishAudio" (click)="publisherProperties.publishAudio = !publisherProperties.publishAudio"
|
||||||
[disabled]="session || disableActiveAudio">Audio</mat-checkbox>
|
[disabled]="session || !publishTo">Audio</mat-checkbox>
|
||||||
<mat-checkbox class="active-video-checkbox" name="activeVideo" (change)="toggleActiveVideo()" [checked]="activeVideo && checkActiveVideo"
|
<mat-checkbox class="active-video-checkbox" name="activeVideo" [(ngModel)]="publisherProperties.publishVideo" (click)="publisherProperties.publishVideo = !publisherProperties.publishVideo"
|
||||||
[disabled]="session || disableActiveVideo">Video</mat-checkbox>
|
[disabled]="session || !publishTo">Video</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="35">
|
<div fxFlex="35">
|
||||||
<mat-radio-group [(ngModel)]="optionsVideo" [disabled]="session || disableRadioButtons" [ngModelOptions]="{standalone: true}">
|
<mat-radio-group [(ngModel)]="optionsVideo" (change)="updateOptionsVideo($event)" [disabled]="session || !publishTo" [ngModelOptions]="{standalone: true}">
|
||||||
<div>
|
<div>
|
||||||
<mat-radio-button class="video-radio" value="video" [checked]="checkRadioVideo && optionsVideo==='video'">Video</mat-radio-button>
|
<mat-radio-button class="video-radio" value="video">Video</mat-radio-button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<mat-radio-button class="screen-radio" value="screen" [checked]="checkRadioScreen && optionsVideo==='screen'">Screen</mat-radio-button>
|
<mat-radio-button class="screen-radio" value="screen">Screen</mat-radio-button>
|
||||||
</div>
|
</div>
|
||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
<mat-checkbox class="subscribe-remote-check" name="subscribeToRemote" (change)="subscribeToRemote = !subscribeToRemote" [disabled]="(!sendAudio && !sendVideo) || !publishTo || session"
|
<mat-checkbox class="subscribe-remote-check" name="subscribeToRemote" (click)="subscribeToRemote = !subscribeToRemote" [disabled]="!publishTo || session"
|
||||||
[checked]="(sendAudio || sendVideo) && publishTo && subscribeToRemote">Subscribe
|
[checked]="publishTo && subscribeToRemote">Subscribe
|
||||||
<br>to remote</mat-checkbox>
|
<br>to remote</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="10">
|
<div fxFlex="10">
|
||||||
<div fxLayout="column" class="publisher-btns-div">
|
<div fxLayout="column" class="publisher-btns-div">
|
||||||
<button mat-icon-button title="Publisher properties" [id]="'session-settings-btn-' + index" class="mat-icon-custom" (click)="advancedPublisherOptions()"
|
<button mat-icon-button title="Publisher properties" [id]="'publisher-settings-btn-' + index" class="mat-icon-custom" (click)="openPublisherPropertiesDialog()"
|
||||||
[disabled]="(!sendAudio && !sendVideo) || !publishTo">
|
[disabled]="!publishTo">
|
||||||
<mat-icon class="mat-icon-custom-ic" aria-label="Session properties button">settings</mat-icon>
|
<mat-icon class="mat-icon-custom-ic" aria-label="Session properties button">settings</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button title="Add new publisher to running session" [id]="'session-api-btn-' + index" class="mat-icon-custom" (click)="addNewPublisher()"
|
<button mat-icon-button title="Add new publisher to running session" [id]="'session-api-btn-' + index" class="mat-icon-custom"
|
||||||
[disabled]="!session || ((!sendAudio && !sendVideo) || !publishTo)">
|
(click)="addNewPublisher()" [disabled]="!session || ((!sendAudio && !sendVideo) || !publishTo)">
|
||||||
<mat-icon class="mat-icon-custom-ic" aria-label="Session API button">add_circle</mat-icon>
|
<mat-icon class="mat-icon-custom-ic" aria-label="Session API button">add_circle</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -129,9 +127,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div [attr.id]="'remote-vid-' + session.connection.connectionId" fxFlex="240px" class="video-container">
|
<div [attr.id]="'remote-vid-' + session.connection.connectionId" fxFlex="240px" class="video-container">
|
||||||
<div [attr.id]="'local-vid-' + session.connection.connectionId"></div>
|
<div [attr.id]="'local-vid-' + session.connection.connectionId"></div>
|
||||||
<app-video *ngIf="this.publisher" [streamManager]="this.publisher" [OV]="OV" (updateEventListInParent)="udpateEventFromChild($event)">
|
<app-video *ngIf="this.publisher" [streamManager]="this.publisher" [OV]="OV" [properties]="publisherProperties" (updateEventListInParent)="udpateEventFromChild($event)">
|
||||||
</app-video>
|
</app-video>
|
||||||
<app-video *ngFor="let subscriber of this.subscribers" [streamManager]="subscriber" [OV]="OV" (updateEventListInParent)="udpateEventFromChild($event)" (reSubbed)="updateSubscriberFromChild($event)">
|
<app-video *ngFor="let subscriber of this.subscribers" [streamManager]="subscriber" [OV]="OV" (updateEventListInParent)="udpateEventFromChild($event)"
|
||||||
|
(reSubbed)="updateSubscriberFromChild($event)">
|
||||||
</app-video>
|
</app-video>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,8 @@ import { Subscription } from 'rxjs/Subscription';
|
||||||
import {
|
import {
|
||||||
OpenVidu, Session, Subscriber, Publisher, Stream, Connection,
|
OpenVidu, Session, Subscriber, Publisher, Stream, Connection,
|
||||||
LocalRecorder, VideoInsertMode, StreamEvent, ConnectionEvent,
|
LocalRecorder, VideoInsertMode, StreamEvent, ConnectionEvent,
|
||||||
SessionDisconnectedEvent, SignalEvent, RecordingEvent, VideoElementEvent, PublisherSpeakingEvent, StreamManagerEvent, StreamManager
|
SessionDisconnectedEvent, SignalEvent, RecordingEvent, VideoElementEvent,
|
||||||
|
PublisherSpeakingEvent, StreamManagerEvent, StreamManager, PublisherProperties
|
||||||
} from 'openvidu-browser';
|
} from 'openvidu-browser';
|
||||||
import {
|
import {
|
||||||
OpenVidu as OpenViduAPI,
|
OpenVidu as OpenViduAPI,
|
||||||
|
@ -17,21 +18,19 @@ import {
|
||||||
RecordingMode,
|
RecordingMode,
|
||||||
RecordingLayout
|
RecordingLayout
|
||||||
} from 'openvidu-node-client';
|
} 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 { ExtensionDialogComponent } from '../dialogs/extension-dialog.component';
|
||||||
import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog.component';
|
import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog.component';
|
||||||
import { TestFeedService } from '../../services/test-feed.service';
|
import { TestFeedService } from '../../services/test-feed.service';
|
||||||
import { MuteSubscribersService } from '../../services/mute-subscribers.service';
|
|
||||||
import { EventsDialogComponent } from '../dialogs/events-dialog.component';
|
import { EventsDialogComponent } from '../dialogs/events-dialog.component';
|
||||||
import { SessionPropertiesDialogComponent } from '../dialogs/session-properties-dialog.component';
|
import { SessionPropertiesDialogComponent } from '../dialogs/session-properties-dialog.component';
|
||||||
import { SessionApiDialogComponent } from '../dialogs/session-api-dialog.component';
|
import { SessionApiDialogComponent } from '../dialogs/session-api-dialog.component';
|
||||||
|
import { PublisherPropertiesDialogComponent } from '../dialogs/publisher-properties-dialog.component';
|
||||||
|
|
||||||
|
|
||||||
export interface SessionConf {
|
export interface SessionConf {
|
||||||
subscribeTo: boolean;
|
subscribeTo: boolean;
|
||||||
publishTo: boolean;
|
publishTo: boolean;
|
||||||
sendAudio: boolean;
|
|
||||||
sendVideo: boolean;
|
|
||||||
startSession: boolean;
|
startSession: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +42,10 @@ export interface OpenViduEvent {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-openvidu-instance',
|
selector: 'app-openvidu-instance',
|
||||||
templateUrl: './openvidu-instance.component.html',
|
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 {
|
export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
|
@ -66,30 +68,10 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
// Session options
|
// Session options
|
||||||
subscribeTo;
|
subscribeTo;
|
||||||
publishTo;
|
publishTo;
|
||||||
sendAudio;
|
|
||||||
sendVideo;
|
|
||||||
activeAudio = true;
|
|
||||||
activeVideo = true;
|
|
||||||
sendVideoRadio = true;
|
sendVideoRadio = true;
|
||||||
subscribeToRemote = false;
|
subscribeToRemote = false;
|
||||||
optionsVideo = 'video';
|
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
|
// OpenVidu Browser objects
|
||||||
OV: OpenVidu;
|
OV: OpenVidu;
|
||||||
session: Session;
|
session: Session;
|
||||||
|
@ -105,6 +87,18 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
customSessionId: ''
|
customSessionId: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
publisherProperties: PublisherProperties = {
|
||||||
|
audioSource: undefined,
|
||||||
|
videoSource: undefined,
|
||||||
|
frameRate: 30,
|
||||||
|
resolution: '640x480',
|
||||||
|
mirror: true,
|
||||||
|
publishAudio: true,
|
||||||
|
publishVideo: true
|
||||||
|
};
|
||||||
|
|
||||||
|
publisherPropertiesAux: PublisherProperties;
|
||||||
|
|
||||||
sessionEvents = {
|
sessionEvents = {
|
||||||
connectionCreated: true,
|
connectionCreated: true,
|
||||||
connectionDestroyed: true,
|
connectionDestroyed: true,
|
||||||
|
@ -139,14 +133,11 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.subscribeTo = this.sessionConf.subscribeTo;
|
this.subscribeTo = this.sessionConf.subscribeTo;
|
||||||
this.publishTo = this.sessionConf.publishTo;
|
this.publishTo = this.sessionConf.publishTo;
|
||||||
this.sendAudio = this.sessionConf.sendAudio;
|
this.publisherPropertiesAux = Object.assign({}, this.publisherProperties);
|
||||||
this.sendVideo = this.sessionConf.sendVideo;
|
|
||||||
|
|
||||||
if (!this.publishTo) {
|
if (!this.publishTo) {
|
||||||
this.publishTo = !this.publishTo;
|
this.publishTo = !this.publishTo;
|
||||||
this.togglePublishTo();
|
this.togglePublishTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sessionConf.startSession) {
|
if (this.sessionConf.startSession) {
|
||||||
this.joinSession();
|
this.joinSession();
|
||||||
}
|
}
|
||||||
|
@ -242,76 +233,49 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
togglePublishTo(): void {
|
togglePublishTo(): void {
|
||||||
this.publishTo = !this.publishTo;
|
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) {
|
if (this.publishTo) {
|
||||||
this.checkRadioVideo = true;
|
this.publisherProperties = this.publisherPropertiesAux;
|
||||||
this.optionsVideo = 'video';
|
|
||||||
} else {
|
} else {
|
||||||
this.checkRadioVideo = false;
|
this.publisherPropertiesAux = Object.assign({}, this.publisherProperties);
|
||||||
this.optionsVideo = '';
|
this.publisherProperties.publishAudio = false;
|
||||||
|
this.publisherProperties.publishVideo = false;
|
||||||
|
this.publisherProperties.audioSource = false;
|
||||||
|
this.publisherProperties.videoSource = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.disableSendAudio = !this.publishTo;
|
if (this.publishTo) {
|
||||||
this.disableSendVideo = !this.publishTo;
|
this.optionsVideo = 'video';
|
||||||
this.disableActiveAudio = !this.publishTo;
|
} else {
|
||||||
this.disableActiveVideo = !this.publishTo;
|
this.optionsVideo = '';
|
||||||
this.disableRadioButtons = !this.publishTo;
|
}
|
||||||
|
|
||||||
this.subscribeToRemote = false;
|
this.subscribeToRemote = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSendAudio(): void {
|
toggleSendAudio(): void {
|
||||||
this.sendAudio = !this.sendAudio;
|
if (this.publisherProperties.audioSource === false) {
|
||||||
|
this.publisherProperties.audioSource = this.publisherPropertiesAux.audioSource;
|
||||||
this.activeAudio = this.sendAudio;
|
} else {
|
||||||
this.checkActiveAudio = this.sendAudio;
|
this.publisherPropertiesAux.audioSource = this.publisherProperties.audioSource;
|
||||||
this.disableActiveAudio = !this.sendAudio;
|
this.publisherProperties.audioSource = false;
|
||||||
|
|
||||||
if (!this.sendAudio && !this.sendVideo && this.publishTo) {
|
|
||||||
this.togglePublishTo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSendVideo(): void {
|
toggleSendVideo(): void {
|
||||||
this.sendVideo = !this.sendVideo;
|
if (this.publisherProperties.videoSource === false) {
|
||||||
|
this.publisherProperties.videoSource = this.publisherPropertiesAux.videoSource;
|
||||||
this.activeVideo = this.sendVideo;
|
|
||||||
|
|
||||||
this.checkActiveVideo = this.sendVideo;
|
|
||||||
this.checkRadioScreen = false;
|
|
||||||
if (this.sendVideo) {
|
|
||||||
this.checkRadioVideo = true;
|
|
||||||
this.optionsVideo = 'video';
|
|
||||||
} else {
|
} else {
|
||||||
this.checkRadioVideo = false;
|
this.publisherPropertiesAux.videoSource = this.publisherProperties.videoSource;
|
||||||
this.optionsVideo = '';
|
this.publisherProperties.videoSource = false;
|
||||||
}
|
|
||||||
|
|
||||||
this.disableActiveVideo = !this.sendVideo;
|
|
||||||
this.disableRadioButtons = !this.sendVideo;
|
|
||||||
|
|
||||||
if (!this.sendAudio && !this.sendVideo && this.publishTo) {
|
|
||||||
this.togglePublishTo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleActiveAudio(): void {
|
toggleActiveAudio(): void {
|
||||||
this.activeAudio = !this.activeAudio;
|
this.publisherProperties.publishAudio = !this.publisherProperties.publishAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleActiveVideo(): void {
|
toggleActiveVideo(): void {
|
||||||
this.activeVideo = !this.activeVideo;
|
this.publisherProperties.publishVideo = !this.publisherProperties.publishVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(): void {
|
sendMessage(): void {
|
||||||
|
@ -438,14 +402,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
syncInitPublisher() {
|
syncInitPublisher() {
|
||||||
this.publisher = this.OV.initPublisher(
|
this.publisher = this.OV.initPublisher(
|
||||||
undefined,
|
undefined,
|
||||||
{
|
this.publisherProperties,
|
||||||
audioSource: this.sendAudio ? undefined : false,
|
|
||||||
videoSource: this.sendVideo ? (this.optionsVideo === 'screen' ? 'screen' : undefined) : false,
|
|
||||||
publishAudio: this.activeAudio,
|
|
||||||
publishVideo: this.activeVideo,
|
|
||||||
resolution: '640x480',
|
|
||||||
frameRate: 30
|
|
||||||
},
|
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.warn(err);
|
console.warn(err);
|
||||||
|
@ -467,46 +424,6 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.session.publish(this.publisher);
|
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) {
|
syncSubscribe(session: Session, event) {
|
||||||
this.subscribers.push(session.subscribe(event.stream, undefined));
|
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),
|
openVidu: new OpenViduAPI(this.openviduUrl, this.openviduSecret),
|
||||||
sessionId: !!this.session ? this.session.sessionId : this.sessionName
|
sessionId: !!this.session ? this.session.sessionId : this.sessionName
|
||||||
},
|
},
|
||||||
width: '280px'
|
width: '280px',
|
||||||
|
disableClose: true
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result: string) => {
|
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<string> {
|
getToken(): Promise<string> {
|
||||||
const OV_NodeClient = new OpenViduAPI(this.openviduUrl, this.openviduSecret);
|
const OV_NodeClient = new OpenViduAPI(this.openviduUrl, this.openviduSecret);
|
||||||
if (!this.sessionProperties.customSessionId) {
|
if (!this.sessionProperties.customSessionId) {
|
||||||
|
@ -652,4 +586,19 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.subscribers[this.subscribers.indexOf(oldSubscriber)] = newSubscriber;
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy {
|
||||||
this.users.push({
|
this.users.push({
|
||||||
subscribeTo: true,
|
subscribeTo: true,
|
||||||
publishTo: true,
|
publishTo: true,
|
||||||
sendAudio: true,
|
|
||||||
sendVideo: true,
|
|
||||||
startSession: false
|
startSession: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -69,8 +67,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy {
|
||||||
this.users.push({
|
this.users.push({
|
||||||
subscribeTo: true,
|
subscribeTo: true,
|
||||||
publishTo: true,
|
publishTo: true,
|
||||||
sendAudio: true,
|
|
||||||
sendVideo: true,
|
|
||||||
startSession: this.autoJoin
|
startSession: this.autoJoin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -81,8 +77,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy {
|
||||||
this.users.push({
|
this.users.push({
|
||||||
subscribeTo: true,
|
subscribeTo: true,
|
||||||
publishTo: false,
|
publishTo: false,
|
||||||
sendAudio: false,
|
|
||||||
sendVideo: false,
|
|
||||||
startSession: this.autoJoin
|
startSession: this.autoJoin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -93,8 +87,6 @@ export class TestSessionsComponent implements OnInit, OnDestroy {
|
||||||
this.users.push({
|
this.users.push({
|
||||||
subscribeTo: false,
|
subscribeTo: false,
|
||||||
publishTo: true,
|
publishTo: true,
|
||||||
sendAudio: true,
|
|
||||||
sendVideo: true,
|
|
||||||
startSession: this.autoJoin
|
startSession: this.autoJoin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
<button class="video-btn pub-btn" title="Publish/Unpublish" (click)="pubUnpub()">
|
<button class="video-btn pub-btn" title="Publish/Unpublish" (click)="pubUnpub()">
|
||||||
<mat-icon aria-label="Publish or unpublish" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button class="video-btn pub-video-btn" title="Publish/Unpublish Video" (click)="pubUnpubVideo()">
|
<button *ngIf="streamManager.stream.hasVideo" class="video-btn pub-video-btn" title="Publish/Unpublish Video" (click)="pubUnpubVideo()">
|
||||||
<mat-icon aria-label="Publish or unpublish video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button class="video-btn pub-audio-btn" title="Publish/Unpublish Audio" (click)="pubUnpubAudio()">
|
<button *ngIf="streamManager.stream.hasAudio" class="video-btn pub-audio-btn" title="Publish/Unpublish Audio" (click)="pubUnpubAudio()">
|
||||||
<mat-icon aria-label="Publish or unpublish audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button class="video-btn change-publisher-btn" title="Change publisher" (click)="changePub()">
|
<button class="video-btn change-publisher-btn" title="Change publisher" (click)="changePub()">
|
||||||
|
@ -41,10 +41,10 @@
|
||||||
<button class="video-btn sub-btn" title="Subscribe/Unsubscribe" (click)="subUnsub()">
|
<button class="video-btn sub-btn" title="Subscribe/Unsubscribe" (click)="subUnsub()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="!!pubSubVideoIcon" class="video-btn sub-video-btn" title="Subscribe/Unsubscribe Video" (click)="subUnsubVideo()">
|
<button *ngIf="streamManager.stream.hasVideo && !!pubSubVideoIcon" class="video-btn sub-video-btn" title="Subscribe/Unsubscribe Video" (click)="subUnsubVideo()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="!!pubSubAudioIcon" class="video-btn sub-audio-btn" title="Subscribe/Unsubscribe Audio" (click)="subUnsubAudio()">
|
<button *ngIf="streamManager.stream.hasAudio && !!pubSubAudioIcon" class="video-btn sub-audio-btn" title="Subscribe/Unsubscribe Audio" (click)="subUnsubAudio()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="!!recordIcon" class="video-btn rec-btn" title="Record" (click)="record()">
|
<button *ngIf="!!recordIcon" class="video-btn rec-btn" title="Record" (click)="record()">
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { OpenViduVideoComponent } from './ov-video.component';
|
||||||
export class VideoComponent implements OnInit, OnDestroy {
|
export class VideoComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@Input() streamManager: StreamManager;
|
@Input() streamManager: StreamManager;
|
||||||
|
@Input() properties: any;
|
||||||
@Input() OV: OpenVidu;
|
@Input() OV: OpenVidu;
|
||||||
@Input() eventCollection: any;
|
@Input() eventCollection: any;
|
||||||
|
|
||||||
|
@ -111,13 +112,19 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
this.sendAudio = this.streamManager.stream.hasAudio;
|
this.sendAudio = this.streamManager.stream.hasAudio;
|
||||||
this.sendVideo = this.streamManager.stream.hasVideo;
|
this.sendVideo = this.streamManager.stream.hasVideo;
|
||||||
|
this.audioMuted = !this.properties.publishAudio;
|
||||||
|
this.videoMuted = !this.properties.publishVideo;
|
||||||
|
this.pubSubAudioIcon = this.audioMuted ? 'mic_off' : 'mic';
|
||||||
|
this.pubSubVideoIcon = this.videoMuted ? 'videocam_off' : 'videocam';
|
||||||
this.optionsVideo = this.streamManager.stream.typeOfVideo;
|
this.optionsVideo = this.streamManager.stream.typeOfVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.muteSubscribersSubscription = this.muteSubscribersService.mutedEvent$.subscribe(muteOrUnmute => {
|
this.muteSubscribersSubscription = this.muteSubscribersService.mutedEvent$.subscribe(muteOrUnmute => {
|
||||||
|
if (this.streamManager.remote) {
|
||||||
this.streamManager.videos.forEach(v => {
|
this.streamManager.videos.forEach(v => {
|
||||||
v.video.muted = muteOrUnmute;
|
v.video.muted = muteOrUnmute;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,15 +203,15 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
pubUnpubVideo() {
|
pubUnpubVideo() {
|
||||||
const publisher: Publisher = <Publisher>this.streamManager;
|
const publisher: Publisher = <Publisher>this.streamManager;
|
||||||
publisher.publishVideo(this.videoMuted);
|
|
||||||
this.videoMuted = !this.videoMuted;
|
this.videoMuted = !this.videoMuted;
|
||||||
|
publisher.publishVideo(!this.videoMuted);
|
||||||
this.pubSubVideoIcon = this.videoMuted ? 'videocam_off' : 'videocam';
|
this.pubSubVideoIcon = this.videoMuted ? 'videocam_off' : 'videocam';
|
||||||
}
|
}
|
||||||
|
|
||||||
pubUnpubAudio() {
|
pubUnpubAudio() {
|
||||||
const publisher: Publisher = <Publisher>this.streamManager;
|
const publisher: Publisher = <Publisher>this.streamManager;
|
||||||
publisher.publishAudio(this.audioMuted);
|
|
||||||
this.audioMuted = !this.audioMuted;
|
this.audioMuted = !this.audioMuted;
|
||||||
|
publisher.publishAudio(!this.audioMuted);
|
||||||
this.pubSubAudioIcon = this.audioMuted ? 'mic_off' : 'mic';
|
this.pubSubAudioIcon = this.audioMuted ? 'mic_off' : 'mic';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,8 +240,6 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
screenChange = this.optionsVideo === 'SCREEN' ? true : false;
|
screenChange = this.optionsVideo === 'SCREEN' ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.audioMuted = false;
|
|
||||||
this.videoMuted = false;
|
|
||||||
this.unpublished = false;
|
this.unpublished = false;
|
||||||
|
|
||||||
const otherPublisher = this.OV.initPublisher(
|
const otherPublisher = this.OV.initPublisher(
|
||||||
|
@ -242,8 +247,8 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
{
|
{
|
||||||
audioSource: this.sendAudioChange ? undefined : false,
|
audioSource: this.sendAudioChange ? undefined : false,
|
||||||
videoSource: this.sendVideoChange ? (screenChange ? 'screen' : undefined) : false,
|
videoSource: this.sendVideoChange ? (screenChange ? 'screen' : undefined) : false,
|
||||||
publishAudio: (!this.publisherChanged) ? true : !this.audioMuted,
|
publishAudio: !this.audioMuted,
|
||||||
publishVideo: (!this.publisherChanged) ? true : !this.videoMuted,
|
publishVideo: !this.videoMuted,
|
||||||
resolution: '640x480',
|
resolution: '640x480',
|
||||||
frameRate: 30,
|
frameRate: 30,
|
||||||
insertMode: VideoInsertMode.APPEND
|
insertMode: VideoInsertMode.APPEND
|
||||||
|
@ -272,13 +277,17 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
streamDestroyed: !this.eventCollection.streamDestroyed
|
streamDestroyed: !this.eventCollection.streamDestroyed
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const oldPublisher = <Publisher>this.streamManager;
|
||||||
|
if (oldPublisher.isSubscribedToRemote) {
|
||||||
|
otherPublisher.subscribeToRemote(true);
|
||||||
|
}
|
||||||
|
|
||||||
otherPublisher.once('accessAllowed', () => {
|
otherPublisher.once('accessAllowed', () => {
|
||||||
if (!this.unpublished) {
|
if (!this.unpublished) {
|
||||||
this.streamManager.stream.session.unpublish(<Publisher>this.streamManager);
|
this.streamManager.stream.session.unpublish(oldPublisher);
|
||||||
this.streamManager = otherPublisher;
|
|
||||||
}
|
}
|
||||||
this.streamManager.stream.session.publish(otherPublisher).then(() => {
|
this.streamManager.stream.session.publish(otherPublisher).then(() => {
|
||||||
console.log(this.streamManager);
|
this.streamManager = otherPublisher;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -455,7 +464,7 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
this.showButtons = true;
|
this.showButtons = true;
|
||||||
this.updateEventListInParent.emit({
|
this.updateEventListInParent.emit({
|
||||||
event: 'streamPlaying',
|
event: 'streamPlaying',
|
||||||
content: this.streamManager.stream.streamId
|
content: pub.stream.streamId
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue