twilio-video
Version:
Twilio Video JavaScript Library
319 lines • 10.9 kB
JavaScript
'use strict';
const LocalParticipantSignaling = require('../localparticipant');
const LocalTrackPublicationV2 = require('./localtrackpublication');
const { DEFAULT_LOG_LEVEL } = require('../../util/constants');
const Log = require('../../util/log');
const { buildLogLevels, isDeepEqual } = require('../../util');
/**
* @extends ParticipantSignaling
* @property {BandwidthProfileOptions} bandwidthProfile
* @property {NetworkQualityConfigurationImpl} networkQualityConfiguration
* @property {number} revision
* @emits LocalParticipantV2#updated
*/
class LocalParticipantV2 extends LocalParticipantSignaling {
/**
* Construct a {@link LocalParticipantV2}.
* @param {EncodingParametersImpl} encodingParameters
* @param {NetworkQualityConfigurationImpl} networkQualityConfiguration
* @param {object} [options]
*/
constructor(encodingParameters, networkQualityConfiguration, options) {
options = Object.assign({
logLevel: DEFAULT_LOG_LEVEL,
LocalTrackPublicationV2
}, options);
super();
const logLevels = buildLogLevels(options.logLevel);
Object.defineProperties(this, {
_bandwidthProfile: {
value: null,
writable: true
},
_bandwidthProfileRevision: {
value: 0,
writable: true
},
_encodingParameters: {
value: encodingParameters
},
_removeListeners: {
value: new Map()
},
_LocalTrackPublicationV2: {
value: options.LocalTrackPublicationV2
},
_log: {
value: options.log
? options.log.createLog('default', this)
: new Log('default', this, logLevels, options.loggerName)
},
_publishedRevision: {
writable: true,
value: 0
},
_revision: {
writable: true,
value: 1
},
_signalingRegion: {
value: null,
writable: true
},
audioProcessors: {
value: [],
writable: true
},
bandwidthProfile: {
enumerable: true,
get() {
return this._bandwidthProfile;
}
},
bandwidthProfileRevision: {
enumerable: true,
get() {
return this._bandwidthProfileRevision;
}
},
networkQualityConfiguration: {
enumerable: true,
value: networkQualityConfiguration
},
revision: {
enumerable: true,
get() {
return this._revision;
}
},
signalingRegion: {
enumerable: true,
get() {
return this._signalingRegion;
}
}
});
}
toString() {
return `[LocalParticipantSignaling: ${this.sid}]`;
}
/**
* Set the signalingRegion.
* @param {string} signalingRegion.
*/
setSignalingRegion(signalingRegion) {
if (!this._signalingRegion) {
this._signalingRegion = signalingRegion;
}
}
/**
* Update the {@link BandwidthProfileOptions}.
* @param {BandwidthProfileOptions} bandwidthProfile
*/
setBandwidthProfile(bandwidthProfile) {
if (!isDeepEqual(this._bandwidthProfile, bandwidthProfile)) {
// NOTE(mmalavalli): Object.assign() copies the values of only
// the top level properties. In order to deep copy the object, we
// stringify and parse the object.
this._bandwidthProfile = JSON.parse(JSON.stringify(bandwidthProfile));
this._bandwidthProfileRevision++;
this.didUpdate();
}
}
/**
* Sets the AudioProcessors enabled for this room.
* @param {string[]} audioProcessors
*/
setAudioProcessors(audioProcessors) {
this.audioProcessors = audioProcessors;
}
/**
* returns current {@link EncodingParametersImpl}.
* @returns {EncodingParametersImpl}
*/
getParameters() {
return this._encodingParameters;
}
/**
* Set the {@link EncodingParameters}.
* @param {?EncodingParameters} encodingParameters
* @returns {this}
*/
setParameters(encodingParameters) {
this._encodingParameters.update(encodingParameters);
return this;
}
/**
* Update the {@link LocalParticipantV2} with the new state.
* @param {Published} published
* @returns {this}
*/
update(published) {
if (this._publishedRevision >= published.revision) {
return this;
}
this._publishedRevision = published.revision;
published.tracks.forEach(function (publicationState) {
const localTrackPublicationV2 = this.tracks.get(publicationState.id);
if (localTrackPublicationV2) {
localTrackPublicationV2.update(publicationState);
}
}, this);
return this;
}
updateMediaStates(mediaStates) {
if (!mediaStates || !mediaStates.tracks) {
return this;
}
Array.from(this.tracks.values()).forEach(publication => {
const states = mediaStates.tracks[publication.sid];
if (states) {
publication.updateMediaStates(states);
}
});
return this;
}
/**
* @protected
* @param {DataTrackSender|MediaTrackSender} trackSender
* @param {string} name
* @param {Track.Priority} priority
* @param {?NoiseCancellationVendor} noiseCancellationVendor
* @returns {LocalTrackPublicationV2}
*/
_createLocalTrackPublicationSignaling(trackSender, name, priority, noiseCancellationVendor) {
return new this._LocalTrackPublicationV2(trackSender, name, priority, noiseCancellationVendor, { log: this._log });
}
/**
* Add a {@link LocalTrackPublicationV2} for the given {@link DataTrackSender}
* or {@link MediaTrackSender} to the {@link LocalParticipantV2}.
* @param {DataTrackSender|MediaTrackSender} trackSender
* @param {string} name
* @param {Track.Priority} priority
* @returns {this}
*/
addTrack(trackSender, name, priority, noiseCancellationVendor) {
super.addTrack(trackSender, name, priority, noiseCancellationVendor);
const publication = this.getPublication(trackSender);
let { isEnabled, updatedPriority } = publication;
const updated = () => {
// NOTE(mmalavalli): The LocalParticipantV2's state is only published if
// the "updated" event is emitted due to LocalTrackPublicationV2's
// .isEnabled or .updatedPriority being changed. We do not publish if it is fired due to the
// LocalTrackPublicationV2's .sid being set.
if (isEnabled !== publication.isEnabled || updatedPriority !== publication.updatedPriority) {
this.didUpdate();
isEnabled = publication.isEnabled;
updatedPriority = publication.updatedPriority;
}
};
publication.on('updated', updated);
this._removeListener(publication);
this._removeListeners.set(publication, () => publication.removeListener('updated', updated));
this.didUpdate();
return this;
}
/**
* @private
* @param {LocalTrackPublicationV2} publication
* @returns {void}
*/
_removeListener(publication) {
const removeListener = this._removeListeners.get(publication);
if (removeListener) {
removeListener();
}
}
/**
* Get the current state of the {@link LocalParticipantV2}.
* @returns {object}
*/
getState() {
return {
revision: this.revision,
tracks: Array.from(this.tracks.values()).map(track => track.getState())
};
}
/**
* Increment the revision for the {@link LocalParticipantV2}.
* @private
* @returns {void}
*/
didUpdate() {
this._revision++;
this.emit('updated');
}
/**
* Remove the {@link LocalTrackPublicationV2} for the given {@link DataTrackSender}
* or {@link MediaTrackSender} from the {@link LocalParticipantV2}.
* @param {DataTrackSender|MediaTrackSender} trackSender
* @returns {?LocalTrackPublicationV2}
*/
removeTrack(trackSender) {
const publication = super.removeTrack(trackSender);
if (publication) {
trackSender.removeClone(publication.trackTransceiver);
this._removeListener(publication);
this.didUpdate();
}
return publication;
}
/**
* Updates the verbosity of network quality information.
* @param {NetworkQualityConfiguration} networkQualityConfiguration
* @returns {void}
*/
setNetworkQualityConfiguration(networkQualityConfiguration) {
this.networkQualityConfiguration.update(networkQualityConfiguration);
}
/**
* updates encodings for simulcast layers.
* @param {Track.SID} trackSid
* @param {Array<{enabled: boolean, layer_index: number}>} encodings
* @returns {Promise<string>} string indicating result of the operation. can be one of
* "OK", "INVALID_HINT", "COULD_NOT_APPLY_HINT", "UNKNOWN_TRACK"
*/
setPublisherHint(trackSid, encodings) {
const trackSignaling = Array.from(this.tracks.values()).find(trackPub => trackPub.sid === trackSid);
if (!trackSignaling) {
this._log.warn(`track:${trackSid} not found`);
return Promise.resolve('UNKNOWN_TRACK');
}
return trackSignaling.trackTransceiver.setPublisherHint(encodings);
}
}
/**
* @interface Published
* @property {number} revision
* @property {Array<PublishedTrack>} tracks
*/
/**
* @typedef {CreatedTrack|ReadyTrack|FailedTrack} PublishedTrack
*/
/**
* @interface CreatedTrack
* @property {Track.ID} id
* @property {string} state - "created"
*/
/**
* @interface ReadyTrack
* @property {Track.ID} id
* @property {Track.SID} sid
* @property {string} state - "ready"
*/
/**
* @interface FailedTrack
* @property {Track.ID} id
* @property {TrackError} error
* @property {string} state - "failed"
*/
/**
* @interface TrackError
* @property {number} code
* @property {string} message
*/
/**
* @event LocalParticipantV2#updated
*/
module.exports = LocalParticipantV2;
//# sourceMappingURL=localparticipant.js.map