@skyway-sdk/core
Version:
The official Next Generation JavaScript SDK for SkyWay
485 lines • 18.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sortEncodingParameters = exports.normalizeEncodings = exports.PublicationImpl = void 0;
const common_1 = require("@skyway-sdk/common");
const common_2 = require("@skyway-sdk/common");
const errors_1 = require("../errors");
const data_1 = require("../media/stream/local/data");
const util_1 = require("../util");
__exportStar(require("./factory"), exports);
const log = new common_1.Logger('packages/core/src/publication/index.ts');
/**@internal */
class PublicationImpl {
constructor(args) {
var _a, _b, _c;
this._codecCapabilities = [];
this._encodings = [];
this._state = 'enabled';
this._events = new common_1.Events();
this.onCanceled = this._events.make();
this.onSubscribed = this._events.make();
this.onUnsubscribed = this._events.make();
this.onSubscriptionListChanged = this._events.make();
this.onMetadataUpdated = this._events.make();
this.onEnabled = this._events.make();
this.onDisabled = this._events.make();
this.onStateChanged = this._events.make();
this.onConnectionStateChanged = new common_2.Event();
/**@private */
this._onEncodingsChanged = this._events.make();
/**@private */
this._onReplaceStream = this._events.make();
this._onEnabled = this._events.make();
this.streamEventDisposer = new common_1.EventDisposer();
/**
* @deprecated
* @use {@link LocalPerson.unpublish}
*/
this.cancel = () => new Promise((r, f) => {
let failed = false;
this._channel._unpublish(this.id).catch((e) => {
failed = true;
f(e);
});
this._setStream(undefined);
this.onCanceled
.asPromise(this._context.config.rtcApi.timeout)
.then(() => r())
.catch((e) => {
if (!failed) {
f(e);
}
});
});
this.updateMetadata = (metadata) => new Promise((r, f) => __awaiter(this, void 0, void 0, function* () {
const timestamp = log.info('[start] updateMetadata', yield (0, util_1.createLogPayload)({
operationName: 'Publication.updateMetadata',
channel: this._channel,
}), this);
let failed = false;
this._channel._updatePublicationMetadata(this.id, metadata).catch((e) => {
failed = true;
f(e);
});
this.onMetadataUpdated
.watch((e) => e.metadata === metadata, this._context.config.rtcApi.timeout)
.then(() => __awaiter(this, void 0, void 0, function* () {
r();
log.elapsed(timestamp, '[end] updateMetadata', yield (0, util_1.createLogPayload)({
operationName: 'Publication.updateMetadata',
channel: this._channel,
}), this);
}))
.catch((error) => {
if (!failed) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.updateMetadata',
info: Object.assign(Object.assign({}, errors_1.errors.timeout), { detail: 'publication onMetadataUpdated' }),
path: log.prefix,
context: this._context,
channel: this._channel,
error,
});
}
});
}));
this.disable = () => new Promise((r, f) => __awaiter(this, void 0, void 0, function* () {
// すでに disabled の場合は何もしない
if (this.state === 'disabled') {
r();
return;
}
const timestamp = log.info('[start] disable', yield (0, util_1.createLogPayload)({
operationName: 'Publication.disable',
channel: this._channel,
}), this);
yield this._disableStream();
let failed = false;
this._channel._disablePublication(this.id).catch((e) => {
failed = true;
f(e);
});
this.onDisabled
.asPromise(this._context.config.rtcApi.timeout)
.then(() => __awaiter(this, void 0, void 0, function* () {
r();
log.elapsed(timestamp, '[end] disable', yield (0, util_1.createLogPayload)({
operationName: 'Publication.disable',
channel: this._channel,
}), this);
}))
.catch((e) => {
if (!failed) {
f(e);
}
});
}));
this.enable = () => new Promise((r, f) => __awaiter(this, void 0, void 0, function* () {
if (this.stream == undefined) {
f((0, util_1.createError)({
operationName: 'Publication.enable',
context: this._context,
info: errors_1.errors.canNotEnableRemotePublication,
path: log.prefix,
}));
return;
}
// すでに enabled の場合は何もしない
if (this.state === 'enabled') {
r();
return;
}
const timestamp = log.info('[start] enable', yield (0, util_1.createLogPayload)({
operationName: 'Publication.enable',
channel: this._channel,
}), this);
let failed = false;
this._channel._enablePublication(this.id).catch((e) => {
failed = true;
f(e);
});
this._onEnabled
.asPromise(this._context.config.rtcApi.timeout)
.then(() => __awaiter(this, void 0, void 0, function* () {
yield this._enableStream();
this.onEnabled.emit();
this.onStateChanged.emit();
log.elapsed(timestamp, '[end] enable', yield (0, util_1.createLogPayload)({
operationName: 'Publication.enable',
channel: this._channel,
}), this);
r();
}))
.catch((e) => {
if (!failed) {
f(e);
}
});
}));
this.id = args.id;
this._channel = args.channel;
this._context = this._channel._context;
this.publisher = args.publisher;
this.contentType = args.contentType;
this._metadata = args.metadata;
this.origin = args.origin;
this.setCodecCapabilities((_a = args.codecCapabilities) !== null && _a !== void 0 ? _a : []);
this.setEncodings((0, exports.normalizeEncodings)((_b = args.encodings) !== null && _b !== void 0 ? _b : []));
this._state = args.isEnabled ? 'enabled' : 'disabled';
if (args.stream) {
this._setStream(args.stream);
}
this._analytics = (_c = this._channel.localPerson) === null || _c === void 0 ? void 0 : _c._analytics;
log.debug('publication spawned', this.toJSON());
}
get codecCapabilities() {
return this._codecCapabilities;
}
setCodecCapabilities(_codecCapabilities) {
this._codecCapabilities = _codecCapabilities;
}
get encodings() {
return this._encodings;
}
setEncodings(_encodings) {
this._encodings = _encodings;
}
get stream() {
return this._stream;
}
/**@internal */
_setStream(stream) {
this._stream = stream;
if (stream) {
stream._onConnectionStateChanged
.add((e) => {
log.debug('onConnectionStateChanged', this.id, e);
this.onConnectionStateChanged.emit(e);
})
.disposer(this.streamEventDisposer);
}
else {
this.streamEventDisposer.dispose();
}
}
get metadata() {
return this._metadata;
}
get state() {
return this._state;
}
get deviceName() {
if (this.stream instanceof data_1.LocalDataStream) {
return undefined;
}
else {
const withDeviceStream = this.stream;
return withDeviceStream.track.label;
}
}
get subscriptions() {
return this._channel.subscriptions.filter((s) => s.publication.id === this.id);
}
/**@private */
_updateMetadata(metadata) {
this._metadata = metadata;
this.onMetadataUpdated.emit({ metadata });
}
/**@private */
_disable() {
return __awaiter(this, void 0, void 0, function* () {
yield this._disableStream();
this.onDisabled.emit();
this.onStateChanged.emit();
});
}
/**@private */
_enable() {
if (this.stream) {
this._onEnabled.emit();
}
else {
this._state = 'enabled';
this.onEnabled.emit();
this.onStateChanged.emit();
}
}
/**@private */
_unpublished() {
this._state = 'canceled';
if (this.stream) {
this.stream._unpublished();
}
this.onCanceled.emit();
this.onStateChanged.emit();
this._dispose();
}
/**@private */
_subscribed(subscription) {
this.onSubscribed.emit({ subscription });
this.onSubscriptionListChanged.emit();
}
/**@private */
_unsubscribed(subscription) {
this.onUnsubscribed.emit({ subscription });
this.onSubscriptionListChanged.emit();
}
updateEncodings(encodings) {
log.info('updateEncodings', { encodings }, this);
this.setEncodings((0, exports.normalizeEncodings)((0, exports.sortEncodingParameters)(encodings)));
this._onEncodingsChanged.emit(encodings);
if (this._analytics && !this._analytics.isClosed()) {
// 再送時に他の処理をブロックしないためにawaitしない
void this._analytics.client.sendPublicationUpdateEncodingsReport({
publicationId: this.id,
encodings: this.encodings,
updatedAt: Date.now(),
});
}
}
_disableStream() {
return __awaiter(this, void 0, void 0, function* () {
if (this.state === 'disabled') {
return;
}
this._state = 'disabled';
if (!this.stream) {
return;
}
if (this.stream.contentType === 'data') {
this.stream.setIsEnabled(false);
}
else {
yield this.stream.setEnabled(false).catch((e) => {
log.warn((0, util_1.createWarnPayload)({
channel: this._channel,
operationName: 'Publication._disableStream',
payload: e,
detail: 'setEnabled failed',
}));
});
}
(0, util_1.createLogPayload)({
operationName: 'Publication._disableStream',
channel: this._channel,
})
.then((p) => log.info('publication _disableStream', p, { publication: this }))
.catch(() => { });
});
}
_enableStream() {
return __awaiter(this, void 0, void 0, function* () {
if (this.state === 'enabled') {
return;
}
this._state = 'enabled';
if (!this.stream) {
return;
}
(0, util_1.createLogPayload)({
operationName: 'Publication._enableStream',
channel: this._channel,
})
.then((p) => log.info('publication _enableStream', p, { publication: this }))
.catch(() => { });
if (this.stream.contentType === 'data') {
this.stream.setIsEnabled(true);
}
else {
yield this.stream.setEnabled(true).catch((e) => {
log.warn((0, util_1.createWarnPayload)({
channel: this._channel,
operationName: 'Publication._disableStream',
payload: e,
detail: 'setEnabled failed',
}));
});
}
});
}
replaceStream(stream, options = {}) {
var _a;
log.info('replaceStream', { stream, options }, this);
if (!this.stream) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.replaceStream',
context: this._context,
info: errors_1.errors.canNotUseReplaceStream,
path: log.prefix,
});
}
if (stream.contentType !== this.contentType) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.replaceStream',
context: this._context,
info: errors_1.errors.invalidContentType,
path: log.prefix,
});
}
if ((_a = options.releaseOldStream) !== null && _a !== void 0 ? _a : true) {
const old = this.stream;
old.release();
}
(0, util_1.createLogPayload)({
operationName: 'PublicationImpl.replaceStream',
channel: this._channel,
})
.then((res) => log.debug(res, { old: this.stream, new: stream }))
.catch((e) => e);
stream.setEnabled(this.stream.isEnabled).catch((e) => {
log.error('replaceStream stream.setEnabled', e, this.toJSON());
});
const oldStream = this._stream;
this._setStream(stream);
this._onReplaceStream.emit({ newStream: stream, oldStream });
if (this._analytics && !this._analytics.isClosed()) {
// 再送時に他の処理をブロックしないためにawaitしない
void this._analytics.client.sendMediaDeviceReport({
publicationId: this.id,
mediaDeviceName: this.deviceName,
mediaDeviceTrigger: 'replaceStream',
updatedAt: Date.now(),
});
}
}
getStats(selector) {
if (!this.stream) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.getStats',
context: this._context,
info: errors_1.errors.streamNotExistInSubscription,
path: log.prefix,
});
}
return this.stream._getStats(selector);
}
getRTCPeerConnection(selector) {
if (!this.stream) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.getRTCPeerConnection',
context: this._context,
info: errors_1.errors.streamNotExistInSubscription,
path: log.prefix,
});
}
return this.stream._getRTCPeerConnection(selector);
}
getConnectionState(selector) {
if (!this.stream) {
throw (0, util_1.createError)({
operationName: 'PublicationImpl.getConnectionState',
context: this._context,
info: errors_1.errors.streamNotExistInSubscription,
path: log.prefix,
});
}
return this.stream._getConnectionState(selector);
}
/**@private */
toJSON() {
var _a;
return {
id: this.id,
channelId: this._channel.id,
publisherId: this.publisher.id,
origin: (_a = this.origin) === null || _a === void 0 ? void 0 : _a.id,
contentType: this.contentType,
metadata: this.metadata,
codecCapabilities: this.codecCapabilities,
encodings: this.encodings,
state: this.state,
stream: this.stream,
};
}
_dispose() {
this._events.dispose();
}
}
exports.PublicationImpl = PublicationImpl;
/**@internal */
const normalizeEncodings = (encodings) => encodings.map((e, i) => {
var _a;
return (Object.assign(Object.assign({}, e), { id: (_a = e.id) !== null && _a !== void 0 ? _a : i.toString() }));
});
exports.normalizeEncodings = normalizeEncodings;
const sortEncodingParameters = (encodings) => {
const [encode] = encodings;
if (encode.maxBitrate) {
// 小から大
return encodings.sort((a, b) => a.maxBitrate - b.maxBitrate);
}
else if (encode.scaleResolutionDownBy) {
//大から小
return encodings.sort((a, b) => b.scaleResolutionDownBy - a.scaleResolutionDownBy);
}
else if (encode.maxFramerate) {
// 小から大
return encodings.sort((a, b) => a.maxFramerate - b.maxFramerate);
}
return encodings;
};
exports.sortEncodingParameters = sortEncodingParameters;
//# sourceMappingURL=index.js.map