openvidu/openvidu-testapp/src/app/components/track/track.component.ts

180 lines
4.5 KiB
TypeScript
Raw Normal View History

import {
Component,
ElementRef,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core';
import {
TrackPublication,
LocalParticipant,
Track,
TrackEvent,
LocalTrack,
RemoteTrack,
RemoteTrackPublication,
AudioTrack,
VideoTrack,
} from 'livekit-client';
import {
TestAppEvent,
TestFeedService,
} from 'src/app/services/test-feed.service';
import {
registerTrackEventListeners,
removeAllManagedListeners,
} from 'src/app/utils/event-listener-utils';
2024-07-02 19:19:05 +02:00
@Component({
2025-02-19 12:03:43 +01:00
selector: 'app-track',
template: '',
2024-07-02 19:19:05 +02:00
})
export class TrackComponent {
@Output()
newTrackEvent = new EventEmitter<{
eventType: TrackEvent;
eventCategory: 'TrackEvent';
eventContent: any;
eventDescription: string;
}>();
2024-07-02 19:19:05 +02:00
@Input()
trackPublication: TrackPublication;
@Input()
localParticipant: LocalParticipant | undefined;
@Input()
earlyTrackEvents: Map<string, TestAppEvent[]> = new Map();
@Input()
earlyTrackListeners: Map<string, Map<string, (...args: any[]) => void>> = new Map();
protected finalElementRefId: string = '';
private indexId: string;
private trackId: string;
2024-07-02 19:19:05 +02:00
public _track: Track | undefined;
@ViewChild('mediaElement') protected elementRef: ElementRef;
2024-07-02 19:19:05 +02:00
trackSubscribed: boolean = true;
trackEnabled: boolean = true;
private trackEventListeners: Map<string, (...args: any[]) => void> = new Map();
constructor(protected testFeedService: TestFeedService) {}
2024-07-02 19:19:05 +02:00
@Input() set index(index: number) {
this.indexId = index.toString();
this.finalElementRefId = `participant-${this.indexId}-${this.trackId}`;
}
@Input() set track(track: AudioTrack | VideoTrack | undefined) {
this._track = track;
// Drain early track events buffered before this component existed
if (this._track) {
const key = this._track.sid || this._track.mediaStreamID;
const earlyEvents = this.earlyTrackEvents?.get(key);
if (earlyEvents) {
for (const event of earlyEvents) {
this.newTrackEvent.emit(event as any);
}
this.earlyTrackEvents.delete(key);
}
const earlyListeners = this.earlyTrackListeners?.get(key);
if (earlyListeners) {
removeAllManagedListeners(this._track, earlyListeners);
this.earlyTrackListeners.delete(key);
}
}
this.setupTrackEventListeners();
this.trackId = `-${this.getTrackOrigin()}--${this._track?.kind}--${
this._track?.source
}--${this._track?.sid}`;
if (this._track?.sid !== this._track?.mediaStreamID) {
this.trackId += `--${this._track?.mediaStreamID}`;
}
this.trackId = this.trackId.replace(/[^0-9a-z-A-Z_-]+/g, '');
this.finalElementRefId = `participant-${this.indexId}-${this.trackId}`;
this.attachTrack();
}
ngAfterViewInit() {
this.attachTrack();
}
ngOnDestroy() {
if (this.elementRef) {
this._track?.detach(this.elementRef.nativeElement);
}
}
private attachTrack() {
if (
this.elementRef &&
(this._track?.kind === Track.Kind.Video ||
(this._track?.kind === Track.Kind.Audio && !this.localParticipant))
) {
this._track.attach(this.elementRef.nativeElement);
}
}
2024-07-02 19:19:05 +02:00
protected async unpublishTrack() {
await this.localParticipant?.unpublishTrack(this._track as LocalTrack);
2024-07-02 19:19:05 +02:00
}
protected async toggleSubscribeTrack() {
this.trackSubscribed = !this.trackSubscribed;
await (this.trackPublication as RemoteTrackPublication).setSubscribed(
this.trackSubscribed
);
}
2024-07-02 19:19:05 +02:00
protected async toggleEnableTrack() {
this.trackEnabled = !this.trackEnabled;
await (this.trackPublication as RemoteTrackPublication).setEnabled(
this.trackEnabled
);
}
protected setupTrackEventListeners() {
if (!this._track) return;
2024-07-02 19:19:05 +02:00
// Clear previous listeners (in case track changed)
removeAllManagedListeners(this._track, this.trackEventListeners);
this.trackEventListeners = registerTrackEventListeners(
this._track,
(eventType, eventContent, eventDescription) => {
this.newTrackEvent.emit({
eventType,
eventCategory: 'TrackEvent',
eventContent,
eventDescription,
});
}
);
2024-07-02 19:19:05 +02:00
}
protected getTrackOrigin(): string {
let origin: string;
if (this._track instanceof RemoteTrack) {
2024-07-02 19:19:05 +02:00
origin = 'remote';
} else if (this._track instanceof LocalTrack) {
2024-07-02 19:19:05 +02:00
origin = 'local';
} else {
origin = 'unknown';
}
return origin;
}
updateEventList(event: TestAppEvent) {
this.testFeedService.pushNewEvent({ user: this.index, event });
}
}