Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated modules/rtc/JitsiTrack #2656

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 74 additions & 57 deletions modules/RTC/JitsiTrack.js → modules/RTC/JitsiTrack.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { getLogger } from '@jitsi/logger';

import EventEmitter from "events";
import JitsiConference from "../../JitsiConference";
import { MediaType } from "../../service/RTC/MediaType";
import { VideoType } from "../../service/RTC/VideoType";
import TraceablePeerConnection from "./TraceablePeerConnection";
import RTCUtils from './RTCUtils';
import * as JitsiTrackEvents from '../../JitsiTrackEvents';
import { MediaType } from '../../service/RTC/MediaType';
import browser from '../browser';
import EventEmitter from '../util/EventEmitter';

import RTCUtils from './RTCUtils';

const logger = getLogger(__filename);

Expand All @@ -22,6 +23,17 @@ const trackHandler2Prop = {
* Represents a single media track (either audio or video).
*/
export default class JitsiTrack extends EventEmitter {
public conference: JitsiConference | null;
public audioLevel: number;
public containers: HTMLElement[];
public handlers: Map<string, Function>;
public type: MediaType;
public disposed: boolean;
private stream: MediaStream;
private track: MediaStreamTrack;
private videoType: VideoType;
private _streamInactiveHandler: Function | null;

/* eslint-disable max-params */
/**
* Represents a single media track (either audio or video).
Expand All @@ -36,12 +48,12 @@ export default class JitsiTrack extends EventEmitter {
* @param videoType the VideoType for this track if any
*/
constructor(
conference,
stream,
track,
streamInactiveHandler,
trackMediaType,
videoType) {
conference: JitsiConference | null,
stream: MediaStream,
track: MediaStreamTrack,
streamInactiveHandler: Function,
trackMediaType: MediaType,
videoType: VideoType) {
super();

/**
Expand Down Expand Up @@ -83,11 +95,13 @@ export default class JitsiTrack extends EventEmitter {
* a onended event on the MediaStreamTrack.
* @param {Function} handler the handler
*/
_addMediaStreamInactiveHandler(handler) {
_addMediaStreamInactiveHandler(handler: Function): void {
if (browser.isFirefox() || browser.isWebKitBased()) {
this.track.onended = handler;
this.track.onended = handler as (this: MediaStreamTrack, ev: Event) => any;
} else {
this.stream.oninactive = handler;
this.stream.getTracks().forEach(track => {
track.onended = handler as (this: MediaStreamTrack, ev: Event) => any;
});
}
}

Expand All @@ -99,7 +113,7 @@ export default class JitsiTrack extends EventEmitter {
* 'audio' element.
* @private
*/
_attachTTFMTracker(container) { // eslint-disable-line no-unused-vars
_attachTTFMTracker(container: HTMLElement): void { // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}

Expand All @@ -110,7 +124,7 @@ export default class JitsiTrack extends EventEmitter {
* 'audio' element.
* @private
*/
_onTrackAttach(container) { // eslint-disable-line no-unused-vars
_onTrackAttach(container: HTMLElement): void { // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}

Expand All @@ -121,7 +135,7 @@ export default class JitsiTrack extends EventEmitter {
* 'audio' element.
* @private
*/
_onTrackDetach(container) { // eslint-disable-line no-unused-vars
_onTrackDetach(container: HTMLElement): void { // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}

Expand All @@ -131,7 +145,7 @@ export default class JitsiTrack extends EventEmitter {
* @param {string} type the type of the handler that is going to be set
* @param {Function} handler the handler.
*/
_setHandler(type, handler) {
_setHandler(type: string, handler: Function): void {
if (!trackHandler2Prop.hasOwnProperty(type)) {
logger.error(`Invalid handler type ${type}`);

Expand All @@ -157,7 +171,7 @@ export default class JitsiTrack extends EventEmitter {
* @param {MediaStream} stream the new stream.
* @protected
*/
_setStream(stream) {
_setStream(stream: MediaStream): void {
if (this.stream === stream) {
return;
}
Expand All @@ -182,7 +196,7 @@ export default class JitsiTrack extends EventEmitter {
* Unregisters all event handlers bound to the underlying media stream/track
* @private
*/
_unregisterHandlers() {
_unregisterHandlers(): void {
if (!this.stream) {
logger.warn(
`${this}: unable to unregister handlers - no stream object`);
Expand Down Expand Up @@ -211,7 +225,7 @@ export default class JitsiTrack extends EventEmitter {
*
* @returns {void}
*/
attach(container) {
attach(container: HTMLElement): Promise<void> {
let result = Promise.resolve();

if (this.stream) {
Expand All @@ -232,7 +246,7 @@ export default class JitsiTrack extends EventEmitter {
* container can be a 'video', 'audio' or 'object' HTML element instance to
* which this JitsiTrack is currently attached.
*/
detach(container) {
detach(container?: HTMLElement): void {
for (let cs = this.containers, i = cs.length - 1; i >= 0; --i) {
const c = cs[i];

Expand Down Expand Up @@ -260,7 +274,7 @@ export default class JitsiTrack extends EventEmitter {
*
* @returns {Promise}
*/
dispose() {
dispose(): Promise<void> {
const p = Promise.resolve();

if (this.disposed) {
Expand All @@ -279,69 +293,69 @@ export default class JitsiTrack extends EventEmitter {
* Returns id of the track.
* @returns {string|null} id of the track or null if this is fake track.
*/
getId() {
getId(): string | null {
return this.getStreamId();
}

/**
* Returns the WebRTC MediaStream instance.
*/
getOriginalStream() {
getOriginalStream(): MediaStream {
return this.stream;
}

/**
* Returns the source name of the track.
* @returns {String|undefined}
*/
getSourceName() { // eslint-disable-line no-unused-vars
getSourceName(){ // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}

/**
* Returns the primary SSRC associated with the track.
* @returns {number}
*/
getSsrc() { // eslint-disable-line no-unused-vars
getSsrc(){ // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}

/**
* Returns the ID of the underlying WebRTC Media Stream(if any)
* @returns {String|null}
*/
getStreamId() {
getStreamId(): string | null {
return this.stream ? this.stream.id : null;
}

/**
* Return the underlying WebRTC MediaStreamTrack
* @returns {MediaStreamTrack}
*/
getTrack() {
getTrack(): MediaStreamTrack {
return this.track;
}

/**
* Return the underlying WebRTC MediaStreamTrack label
* @returns {string}
*/
getTrackLabel() {
getTrackLabel(): string {
return this.track.label;
}

/**
* Returns the ID of the underlying WebRTC MediaStreamTrack(if any)
* @returns {String|null}
*/
getTrackId() {
getTrackId(): string | null {
return this.track ? this.track.id : null;
}

/**
* Returns the type (audio or video) of this track.
*/
getType() {
getType(): MediaType {
return this.type;
}

Expand All @@ -350,7 +364,7 @@ export default class JitsiTrack extends EventEmitter {
* eventual video type.
* @returns {string}
*/
getUsageLabel() {
getUsageLabel(): string {
if (this.isAudioTrack()) {
return 'mic';
}
Expand All @@ -361,21 +375,21 @@ export default class JitsiTrack extends EventEmitter {
/**
* Returns the video type (camera or desktop) of this track.
*/
getVideoType() {
getVideoType(): VideoType {
return this.videoType;
}

/**
* Returns the height of the track in normalized landscape format.
*/
getHeight() {
getHeight(): number {
return Math.min(this.track.getSettings().height, this.track.getSettings().width);
}

/**
* Returns the width of the track in normalized landscape format.
*/
getWidth() {
getWidth(): number {
return Math.max(this.track.getSettings().height, this.track.getSettings().width);
}

Expand All @@ -385,7 +399,7 @@ export default class JitsiTrack extends EventEmitter {
* will return that stream is active (in case of FF).
* @returns {boolean} whether MediaStream is active.
*/
isActive() {
isActive(): boolean {
if (typeof this.stream.active !== 'undefined') {
return this.stream.active;
}
Expand All @@ -396,7 +410,7 @@ export default class JitsiTrack extends EventEmitter {
/**
* Check if this is an audio track.
*/
isAudioTrack() {
isAudioTrack(): boolean {
return this.getType() === MediaType.AUDIO;
}

Expand All @@ -405,7 +419,7 @@ export default class JitsiTrack extends EventEmitter {
* @abstract
* @return {boolean} 'true' if it's a local track or 'false' otherwise.
*/
isLocal() {
isLocal(): boolean {
throw new Error('Not implemented by subclass');
}

Expand All @@ -414,14 +428,14 @@ export default class JitsiTrack extends EventEmitter {
*
* @return {boolean} - true if track represents a local audio track, false otherwise.
*/
isLocalAudioTrack() {
isLocalAudioTrack(): boolean {
return this.isAudioTrack() && this.isLocal();
}

/**
* Check if this is a video track.
*/
isVideoTrack() {
isVideoTrack(): boolean {
return this.getType() === MediaType.VIDEO;
}

Expand All @@ -431,7 +445,7 @@ export default class JitsiTrack extends EventEmitter {
* @return {boolean} <tt>true</tt> if the underlying
* <tt>MediaStreamTrack</tt> is muted or <tt>false</tt> otherwise.
*/
isWebRTCTrackMuted() {
isWebRTCTrackMuted(): boolean {
return this.track && this.track.muted;
}

Expand All @@ -443,14 +457,14 @@ export default class JitsiTrack extends EventEmitter {
* a local track if the audio level was measured outside of the
* peerconnection (see /modules/statistics/LocalStatsCollector.js).
*/
setAudioLevel(audioLevel, tpc) {
setAudioLevel(audioLevel: number, tpc?: TraceablePeerConnection): void {
let newAudioLevel = audioLevel;

// When using getSynchornizationSources on the audio receiver to gather audio levels for
// remote tracks, browser reports last known audio levels even when the remote user is
// audio muted, we need to reset the value to zero here so that the audio levels are cleared.
// Remote tracks have the tpc info present while local tracks do not.
if (browser.supportsReceiverStats() && typeof tpc !== 'undefined' && this.isMuted()) {
if (browser.supportsReceiverStats() && typeof tpc !== 'undefined' && this.isWebRTCTrackMuted()) {
newAudioLevel = 0;
}

Expand Down Expand Up @@ -481,23 +495,21 @@ export default class JitsiTrack extends EventEmitter {
* @emits JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED
* @returns {Promise}
*/
setAudioOutput(audioOutputDeviceId) {
setAudioOutput(audioOutputDeviceId: string): Promise<void> {
if (!RTCUtils.isDeviceChangeAvailable('output')) {
return Promise.reject(
new Error('Audio output device change is not supported'));
}

// All audio communication is done through audio tracks, so ignore
// changing audio output for video tracks at all.
if (this.isVideoTrack()) {
return Promise.resolve();
}

return (
Promise.all(
this.containers.map(
element =>
element.setSinkId(audioOutputDeviceId)
this.containers.map(element => {
if (element instanceof HTMLMediaElement) {
return element.setSinkId(audioOutputDeviceId)
.catch(error => {
logger.warn(
'Failed to change audio output device on'
Expand All @@ -506,21 +518,26 @@ export default class JitsiTrack extends EventEmitter {
element,
error);
throw error;
}))
});
} else {
return Promise.resolve();
}
})
)
.then(() => {
this.emit(
JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED,
audioOutputDeviceId);
}));
.then(() => {
this.emit(
JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED,
audioOutputDeviceId);
})
);
}

/**
* Assigns the source name to a track.
* @param {String} name - The name to be assigned to the track.
* @returns {void}
*/
setSourceName(name) { // eslint-disable-line no-unused-vars
setSourceName(name: string): void { // eslint-disable-line no-unused-vars
// Should be defined by the classes that are extending JitsiTrack
}
}
Loading