diff --git a/openvidu-testapp/src/app/app.module.ts b/openvidu-testapp/src/app/app.module.ts index d9b0de79..d4302bcc 100644 --- a/openvidu-testapp/src/app/app.module.ts +++ b/openvidu-testapp/src/app/app.module.ts @@ -45,6 +45,7 @@ import { TableVideoComponent } from './components/users-table/table-video.compon import { CallbackPipe } from './pipes/callback.pipe'; import { AppRoutingModule } from './app.routing'; import { VideoResolutionComponent } from './components/dialogs/options-dialog/video-resolution/video-resolution.component'; +import { InfoDialogComponent } from './components/dialogs/info-dialog/info-dialog.component'; @NgModule({ declarations: [ @@ -63,6 +64,7 @@ import { VideoResolutionComponent } from './components/dialogs/options-dialog/vi CallbackPipe, OptionsDialogComponent, VideoResolutionComponent, + InfoDialogComponent, ], imports: [ FormsModule, diff --git a/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.css new file mode 100644 index 00000000..fa404414 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.css @@ -0,0 +1,13 @@ +mat-form-field { + width: 100%; +} + +textarea { + font-size: 13px !important; + line-height: 18px !important; +} + +#subtitle { + font-size: 12px; + margin: 0 10px 0 10px; +} diff --git a/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.html new file mode 100644 index 00000000..8a1f40e9 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.html @@ -0,0 +1,27 @@ +
+

{{ title }}

+

{{ subtitle }}

+ + + + + + + + + + + +
diff --git a/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.spec.ts b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.spec.ts new file mode 100644 index 00000000..16891346 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoDialogComponent } from './info-dialog.component'; + +describe('InfoDialogComponent', () => { + let component: InfoDialogComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [InfoDialogComponent] + }); + fixture = TestBed.createComponent(InfoDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.ts new file mode 100644 index 00000000..753dcdea --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/info-dialog/info-dialog.component.ts @@ -0,0 +1,84 @@ +import { Component, Inject, NgZone, ViewChild } from '@angular/core'; +import { CdkTextareaAutosize } from '@angular/cdk/text-field'; +import { take } from 'rxjs/operators'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-info-dialog', + templateUrl: './info-dialog.component.html', + styleUrls: ['./info-dialog.component.css'], +}) +export class InfoDialogComponent { + title: string; + subtitle: string; + updateFunction: () => Promise; + + textAreaValue: string; + + @ViewChild('autosize') autosize: CdkTextareaAutosize; + + constructor( + @Inject(MAT_DIALOG_DATA) + public data: { + title: string; + subtitle: string; + updateFunction: () => Promise; + }, + private _ngZone: NgZone + ) { + this.title = data.title; + this.subtitle = data.subtitle; + this.updateFunction = data.updateFunction; + + this.updateValue(); + + // this.publisher + // .getSenders() + // .filter((sender) => { + // return sender.track?.kind === 'video'; + // })[0] + // .getStats() + // .then((stats) => { + // stats.forEach((report) => { + // if ( + // report.type === 'outbound-rtp' || + // report.type === 'remote-inbound-rtp' + // ) { + // console.log(report.type); + // console.log(report); + // this.textAreaValue = report.framesPerSecond; + // } + // }); + // }); + + // this.publisher.getConnectedAddress().then((address) => { + // this.textAreaValue = address! + '\n'; + // this.textAreaValue += this.publisher.getConnectionState() + '\n'; + // this.textAreaValue += this.publisher.getICEConnectionState() + '\n'; + // this.textAreaValue += this.publisher.getSignallingState() + '\n'; + // this.textAreaValue += this.publisher.getLocalDescription()!.sdp + '\n'; + // this.textAreaValue += this.publisher.getRemoteDescription()!.sdp + '\n'; + // this.subscriber.getConnectedAddress().then((address) => { + // this.textAreaValue += address! + '\n'; + // this.textAreaValue += this.subscriber.getConnectionState() + '\n'; + // this.textAreaValue += this.subscriber.getICEConnectionState() + '\n'; + // this.textAreaValue += this.subscriber.getSignallingState() + '\n'; + // this.textAreaValue += this.subscriber.getLocalDescription()!.sdp + '\n'; + // this.textAreaValue += + // this.subscriber.getRemoteDescription()!.sdp + '\n'; + // }); + // }); + } + + async updateValue() { + this.textAreaValue = await this.updateFunction(); + this.triggerResize(); + } + + triggerResize() { + // Wait for changes to be applied, then trigger textarea resize. + this._ngZone.onStable + .pipe(take(1)) + .subscribe(() => this.autosize.resizeToFitContent(true)); + } +} diff --git a/openvidu-testapp/src/app/components/dialogs/options-dialog/options-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/options-dialog/options-dialog.component.html index 22418d2a..653b08c5 100644 --- a/openvidu-testapp/src/app/components/dialogs/options-dialog/options-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/options-dialog/options-dialog.component.html @@ -155,7 +155,8 @@ scalabilityMode - {{mode}} + {{mode}} 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 7e2325be..ace67622 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 @@ -56,6 +56,9 @@
{{room.name}}
+ 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 1a9f3dbd..13814263 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 @@ -43,6 +43,8 @@ import { RoomApiDialogComponent } from '../dialogs/room-api-dialog/room-api-dial import { RoomApiService } from 'src/app/services/room-api.service'; import { EventsDialogComponent } from '../dialogs/events-dialog/events-dialog.component'; import { OptionsDialogComponent } from '../dialogs/options-dialog/options-dialog.component'; +import PCTransport from 'livekit-client/dist/src/room/PCTransport'; +import { InfoDialogComponent } from '../dialogs/info-dialog/info-dialog.component'; @Component({ selector: 'app-openvidu-instance', @@ -1052,7 +1054,7 @@ export class OpenviduInstanceComponent { }); dialogRef.afterClosed().subscribe((result) => { if (!!result) { - this.roomOptions = result; + this.roomOptions = result.roomOptions; this.createLocalTracksOptions = result.createLocalTracksOptions; this.screenShareCaptureOptions = result.screenShareCaptureOptions; this.trackPublishOptions = result.trackPublishOptions; @@ -1132,4 +1134,44 @@ export class OpenviduInstanceComponent { } this.room?.localParticipant.publishData(data, options); } + + openInfoDialog() { + const updateFunction = async (): Promise => { + const pub: PCTransport = this.getPublisherPC()!; + const sub: PCTransport = this.getSubscriberPC()!; + return JSON.stringify( + { + publisher: { + connectedAddress: await pub.getConnectedAddress(), + connectionState: pub.getConnectionState(), + iceConnectionState: pub.getICEConnectionState(), + signallingState: pub.getSignallingState(), + }, + subscriber: { + connectedAddress: await sub.getConnectedAddress(), + connectionState: sub.getConnectionState(), + iceConnectionState: sub.getICEConnectionState(), + signallingState: sub.getSignallingState(), + }, + }, + null, + 2 + ); + }; + this.dialog.open(InfoDialogComponent, { + data: { + title: 'PCTransports info', + updateFunction, + }, + minWidth: '50vh' + }); + } + + getPublisherPC(): PCTransport | undefined { + return this.room?.localParticipant.engine.pcManager?.publisher; + } + + getSubscriberPC(): PCTransport | undefined { + return this.room?.localParticipant.engine.pcManager?.subscriber; + } } diff --git a/openvidu-testapp/src/app/components/participant/participant.component.html b/openvidu-testapp/src/app/components/participant/participant.component.html index d8ca5982..6b06e1b7 100644 --- a/openvidu-testapp/src/app/components/participant/participant.component.html +++ b/openvidu-testapp/src/app/components/participant/participant.component.html @@ -55,9 +55,9 @@ [localParticipant]="localParticipant" [index]="index" (newTrackEvent)="events.push($event)">
- + (newTrackEvent)="events.push($event)" [attr.id]="'user-' + index + '-' + participant.identity + '-video-' + i">
\ No newline at end of file diff --git a/openvidu-testapp/src/app/components/track/track.component.ts b/openvidu-testapp/src/app/components/track/track.component.ts index fa2dd6be..6a10a585 100644 --- a/openvidu-testapp/src/app/components/track/track.component.ts +++ b/openvidu-testapp/src/app/components/track/track.component.ts @@ -1,16 +1,33 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { TrackPublication, LocalParticipant, Track, TrackEvent, LocalTrack, RemoteTrack, TrackEventCallbacks } from 'livekit-client'; -import { TestAppEvent, TestFeedService } from 'src/app/services/test-feed.service'; +import { + TrackPublication, + LocalParticipant, + Track, + TrackEvent, + LocalTrack, + RemoteTrack, + TrackEventCallbacks, + LocalTrackPublication, + RemoteTrackPublication, +} from 'livekit-client'; +import { + TestAppEvent, + TestFeedService, +} from 'src/app/services/test-feed.service'; @Component({ selector: 'app-track', template: '', - styleUrls: [] + styleUrls: [], }) export class TrackComponent { - @Output() - newTrackEvent = new EventEmitter<{ eventType: TrackEvent, eventCategory: 'TrackEvent', eventContent: any, eventDescription: string }>(); + newTrackEvent = new EventEmitter<{ + eventType: TrackEvent; + eventCategory: 'TrackEvent'; + eventContent: any; + eventDescription: string; + }>(); @Input() trackPublication: TrackPublication; @@ -23,28 +40,117 @@ export class TrackComponent { protected track: Track | undefined; - constructor(private testFeedService: TestFeedService) { } + trackSubscribed: boolean = true; + trackEnabled: boolean = true; + + constructor(protected testFeedService: TestFeedService) {} protected async unpublishTrack() { await this.localParticipant?.unpublishTrack(this.track as LocalTrack); } - protected setupTrackEventListeners() { + protected async toggleSubscribeTrack() { + this.trackSubscribed = !this.trackSubscribed; + await (this.trackPublication as RemoteTrackPublication).setSubscribed( + this.trackSubscribed + ); + } + protected async toggleEnableTrack() { + this.trackEnabled = !this.trackEnabled; + await (this.trackPublication as RemoteTrackPublication).setEnabled( + this.trackEnabled + ); + } + + protected setupTrackEventListeners() { // This is a link to the complete list of Track events let callbacks: TrackEventCallbacks; let events: TrackEvent; - this.track?.on(TrackEvent.Message, () => { this.newTrackEvent.emit({ eventType: TrackEvent.Message, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.Muted, () => { this.newTrackEvent.emit({ eventType: TrackEvent.Muted, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.Unmuted, () => { this.newTrackEvent.emit({ eventType: TrackEvent.Unmuted, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.AudioSilenceDetected, () => { this.newTrackEvent.emit({ eventType: TrackEvent.AudioSilenceDetected, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.Restarted, () => { this.newTrackEvent.emit({ eventType: TrackEvent.Restarted, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.Ended, () => { this.newTrackEvent.emit({ eventType: TrackEvent.Ended, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.VisibilityChanged, (visible: boolean) => { this.newTrackEvent.emit({ eventType: TrackEvent.VisibilityChanged, eventCategory: 'TrackEvent', eventContent: { visible, track: this.track }, eventDescription: `${this.track!.source} is visible: ${visible}` }) }) - .on(TrackEvent.VideoDimensionsChanged, (dimensions: Track.Dimensions) => { this.newTrackEvent.emit({ eventType: TrackEvent.VideoDimensionsChanged, eventCategory: 'TrackEvent', eventContent: { dimensions, track: this.track }, eventDescription: `${this.track!.source} ${JSON.stringify(dimensions)}` }) }) - .on(TrackEvent.UpstreamPaused, () => { this.newTrackEvent.emit({ eventType: TrackEvent.UpstreamPaused, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) - .on(TrackEvent.UpstreamResumed, () => { this.newTrackEvent.emit({ eventType: TrackEvent.UpstreamResumed, eventCategory: 'TrackEvent', eventContent: {}, eventDescription: this.track!.source }) }) + this.track + ?.on(TrackEvent.Message, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.Message, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.Muted, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.Muted, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.Unmuted, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.Unmuted, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.AudioSilenceDetected, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.AudioSilenceDetected, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.Restarted, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.Restarted, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.Ended, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.Ended, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.VisibilityChanged, (visible: boolean) => { + this.newTrackEvent.emit({ + eventType: TrackEvent.VisibilityChanged, + eventCategory: 'TrackEvent', + eventContent: { visible, track: this.track }, + eventDescription: `${this.track!.source} is visible: ${visible}`, + }); + }) + .on(TrackEvent.VideoDimensionsChanged, (dimensions: Track.Dimensions) => { + this.newTrackEvent.emit({ + eventType: TrackEvent.VideoDimensionsChanged, + eventCategory: 'TrackEvent', + eventContent: { dimensions, track: this.track }, + eventDescription: `${this.track?.source} ${JSON.stringify( + dimensions + )}`, + }); + }) + .on(TrackEvent.UpstreamPaused, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.UpstreamPaused, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }) + .on(TrackEvent.UpstreamResumed, () => { + this.newTrackEvent.emit({ + eventType: TrackEvent.UpstreamResumed, + eventCategory: 'TrackEvent', + eventContent: {}, + eventDescription: this.track!.source, + }); + }); } protected getTrackOrigin(): string { @@ -62,5 +168,4 @@ export class TrackComponent { updateEventList(event: TestAppEvent) { this.testFeedService.pushNewEvent({ user: this.index, event }); } - } diff --git a/openvidu-testapp/src/app/components/video-track/video-track.component.css b/openvidu-testapp/src/app/components/video-track/video-track.component.css index 530dbf66..6461c57a 100644 --- a/openvidu-testapp/src/app/components/video-track/video-track.component.css +++ b/openvidu-testapp/src/app/components/video-track/video-track.component.css @@ -1,45 +1,65 @@ video { - height: 90px; - width: 120px; + height: 90px; + width: 120px; } .parent-div { - position: relative; - height: 90px; + position: relative; + height: 90px; } .top-div { - position: absolute; - top: 0; + position: absolute; + top: 0; } .bottom-div { - position: absolute; - bottom: 0; + position: absolute; + bottom: 0; } .video-btn { - border: none; - background: rgba(255, 255, 255, 0.75); - cursor: pointer; - padding: 0; - height: 16px; - float: left; + border: none; + background: rgba(255, 255, 255, 0.75); + cursor: pointer; + padding: 0; + height: 16px; + float: left; +} + +.quality-option { + float: right; } .video-btn:hover { - color: #4d4d4d; + color: #4d4d4d; } .video-btn.top-row { - margin-top: 0; - display: inline-flex; - float: right; + margin-top: 0; + display: inline-flex; + float: right; } .video-btn mat-icon { - font-size: 14px; - width: 14px; - height: 14px; - line-height: 16px; -} \ No newline at end of file + font-size: 14px; + width: 14px; + height: 14px; + line-height: 16px; +} + +#max-video-quality { + width: 16px; + height: 16px; + font-size: 10px; + font-weight: bold; +} + +::ng-deep #max-video-quality * { + height: 16px !important; + width: 8px !important; + min-height: 16px !important; + min-width: 8px !important; + padding: 0 !important; + border-color: transparent !important; +} diff --git a/openvidu-testapp/src/app/components/video-track/video-track.component.html b/openvidu-testapp/src/app/components/video-track/video-track.component.html index 44ff8b55..66290456 100644 --- a/openvidu-testapp/src/app/components/video-track/video-track.component.html +++ b/openvidu-testapp/src/app/components/video-track/video-track.component.html @@ -1,16 +1,36 @@
- - + + + + + {{q}} + + +