UNPKG

@snap/camera-kit

Version:
260 lines 15.2 kB
import { __awaiter, __esDecorate, __runInitializers } from "tslib"; import { filter, firstValueFrom, map, of, takeUntil, tap } from "rxjs"; import { dispatch, forActions, inStates, isAction, isState } from "@snap/state-management"; import { Injectable } from "@snap/ts-inject"; import { isLens } from "../lens/Lens"; import { lensCoreFactory } from "../lens-core-module/loader/lensCoreFactory"; import { isLensLaunchDataOrUndefined } from "../lens/LensLaunchData"; import { getTypeName, validate } from "../common/validate"; import { TypedEventTarget } from "../events/TypedEventTarget"; import { TypedCustomEvent } from "../events/TypedCustomEvent"; import { isCameraKitSource } from "../media-sources/CameraKitSource"; import { isPartialCameraKitDeviceOptionsOrUndefined } from "../media-sources/CameraKitSource"; import { cameraKitSourceError } from "../namedErrors"; import { createMediaStreamSource } from "../media-sources/MediaStreamSource"; import { createVideoSource } from "../media-sources/VideoSource"; import { getLogger } from "../logger/logger"; import { errorLoggingDecorator } from "../logger/errorLoggingDecorator"; import { logEntriesFactory } from "../logger/logEntries"; import { pageVisibilityFactory } from "../common/pageVisibility"; import { isUndefined, isValidNumber } from "../common/typeguards"; import { LensPerformanceMetrics } from "./LensPerformanceMetrics"; import { lensStateFactory } from "./lensState"; import { sessionStateFactory } from "./sessionState"; import { lensKeyboardFactory } from "./LensKeyboard"; import { isPublicLensError } from "./CameraKitSessionEvents"; import { frameEventsFactory } from "./frameEvents"; import { prepareScreenRegionsUpdate, isScreenRegions } from "./screenRegions"; const logger = getLogger("CameraKitSession"); function isAllowedSource(value) { return isCameraKitSource(value) || isMediaStream(value) || isHTMLVideoElement(value); } function isMediaStream(value) { return value instanceof MediaStream; } function isHTMLVideoElement(value) { return value instanceof HTMLVideoElement; } function isRenderTargetOrUndefined(value) { return isUndefined(value) || value === "live" || value === "capture"; } let CameraKitSession = (() => { var _a; let _instanceExtraInitializers = []; let _applyLens_decorators; let _removeLens_decorators; let _play_decorators; let _pause_decorators; let _mute_decorators; let _unmute_decorators; let _setSource_decorators; let _setFPSLimit_decorators; let _setScreenRegions_decorators; let _destroy_decorators; return _a = class CameraKitSession { constructor(innerKeyboard, lensCore, sessionState, lensState, logEntries, pageVisibility, frameEvents) { this.innerKeyboard = (__runInitializers(this, _instanceExtraInitializers), innerKeyboard); this.lensCore = lensCore; this.sessionState = sessionState; this.lensState = lensState; this.frameEvents = frameEvents; this.events = new TypedEventTarget(); this.keyboard = innerKeyboard.toPublicInterface(); const outputs = this.lensCore.getOutputCanvases(); this.output = { live: outputs[this.lensCore.CanvasType.Preview.value], capture: outputs[this.lensCore.CanvasType.Capture.value], }; this.playing = { live: false, capture: false, }; this.metrics = new LensPerformanceMetrics(frameEvents); const removeOnHidden = pageVisibility.onPageHidden(() => this.sessionState.dispatch("suspend", this)); const removeOnVisible = pageVisibility.onPageVisible(() => this.sessionState.dispatch("resume", this)); this.removePageVisibilityHandlers = () => { removeOnHidden(); removeOnVisible(); }; this.subscriptions = [ lensCore.errors .pipe(filter((error) => error.name === "LensCoreAbortError")) .subscribe(() => this.destroy()), lensCore.errors .pipe(filter((error) => error.name !== "LensCoreAbortError" && error.isFrameError)) .subscribe(() => this.removeLens()), logEntries .pipe(filter((entry) => entry.level === "error"), map((entry) => entry.messages.find((e) => e instanceof Error)), filter(isPublicLensError)) .subscribe((error) => { const state = lensState.getState(); if (!isState(state, "noLensApplied")) { this.events.dispatchEvent(new TypedCustomEvent("error", { error, lens: state.data })); } else { logger.warn("Lens error occurred even though there is no active lens.", error); } }), ]; } applyLens(lens, launchData) { return __awaiter(this, void 0, void 0, function* () { const action = this.lensState.actions.applyLens({ lens, launchData }); return firstValueFrom(of(action).pipe(dispatch(this.lensState), takeUntil(this.lensState.events.pipe(forActions("applyLens"), filter(([a]) => a !== action))), tap(([a]) => { if (isAction(a, "applyLensFailed") && a.data.lens.id === lens.id) throw a.data.error; }), inStates("lensApplied"), map(() => true)), { defaultValue: false }); }); } removeLens() { return __awaiter(this, void 0, void 0, function* () { if (isState(this.lensState.getState(), "noLensApplied")) return true; return firstValueFrom(of(this.lensState.actions.removeLens()).pipe(dispatch(this.lensState), tap(([a]) => { if (isAction(a, "removeLensFailed")) throw a.data; }), inStates("noLensApplied"), takeUntil(this.lensState.events.pipe(forActions("applyLens"))), map(() => true)), { defaultValue: false }); }); } play(target = "live") { return __awaiter(this, void 0, void 0, function* () { if (this.playing[target]) return; this.playing[target] = true; const type = this.renderTargetToCanvasType(target); return this.lensCore.playCanvas({ type }).catch((error) => { this.playing[target] = false; throw error; }); }); } pause(target = "live") { return __awaiter(this, void 0, void 0, function* () { if (this.playing[target] === false) return; this.playing[target] = false; const type = this.renderTargetToCanvasType(target); return this.lensCore.pauseCanvas({ type }).catch((error) => { this.playing[target] = true; throw error; }); }); } mute(fade = false) { this.lensCore.setAllSoundsMuted({ muted: true, fade, }); } unmute(fade = false) { this.lensCore.setAllSoundsMuted({ muted: false, fade, }); } setSource(source, options = {}) { return __awaiter(this, void 0, void 0, function* () { yield this.safelyDetachSource(); const cameraKitSource = isMediaStream(source) ? createMediaStreamSource(source, options) : isHTMLVideoElement(source) ? createVideoSource(source, options) : source; const priorPlayingState = this.playing; this.playing = { live: false, capture: false, }; yield cameraKitSource.attach(this.lensCore, this.frameEvents, (error) => { logger.error(cameraKitSourceError("Error occurred during source attachment.", error)); }); this.source = cameraKitSource; if (priorPlayingState.live) yield this.play("live"); if (priorPlayingState.capture) yield this.play("capture"); return cameraKitSource; }); } setFPSLimit(fpsLimit) { return __awaiter(this, void 0, void 0, function* () { const fps = fpsLimit < Number.POSITIVE_INFINITY ? fpsLimit : 0; return this.lensCore.setFPSLimit({ fps }); }); } setScreenRegions(regions) { return __awaiter(this, void 0, void 0, function* () { yield this.lensCore.setScreenRegions({ regions: prepareScreenRegionsUpdate(regions), }); }); } destroy() { return __awaiter(this, void 0, void 0, function* () { try { yield this.lensCore.clearAllLenses(); yield this.lensCore.teardown(); } catch (error) { logger.warn("An error occurred in LensCore during the session termination process.", error); } this.subscriptions.forEach((sub) => sub.unsubscribe()); yield this.safelyDetachSource(); this.removePageVisibilityHandlers(); this.sessionState.dispatch("destroy", undefined); this.innerKeyboard.destroy(); this.metrics.destroy(); }); } renderTargetToCanvasType(target) { return target === "capture" ? this.lensCore.CanvasType.Capture : this.lensCore.CanvasType.Preview; } safelyDetachSource() { return __awaiter(this, void 0, void 0, function* () { if (this.source) { try { yield this.source.detach((error) => { logger.error(cameraKitSourceError("Error occurred during source detachment.", error)); }); } catch (error) { logger.error(cameraKitSourceError(`Detaching prior source of type ${getTypeName(this.source)} failed.`, error)); } } }); } }, (() => { _applyLens_decorators = [validate(isLens, isLensLaunchDataOrUndefined), errorLoggingDecorator(logger)]; _removeLens_decorators = [errorLoggingDecorator(logger)]; _play_decorators = [validate(isRenderTargetOrUndefined), errorLoggingDecorator(logger)]; _pause_decorators = [validate(isRenderTargetOrUndefined), errorLoggingDecorator(logger)]; _mute_decorators = [errorLoggingDecorator(logger)]; _unmute_decorators = [errorLoggingDecorator(logger)]; _setSource_decorators = [validate(isAllowedSource, isPartialCameraKitDeviceOptionsOrUndefined), errorLoggingDecorator(logger)]; _setFPSLimit_decorators = [validate(isValidNumber), errorLoggingDecorator(logger)]; _setScreenRegions_decorators = [validate(isScreenRegions), errorLoggingDecorator(logger)]; _destroy_decorators = [errorLoggingDecorator(logger)]; __esDecorate(_a, null, _applyLens_decorators, { kind: "method", name: "applyLens", static: false, private: false, access: { has: obj => "applyLens" in obj, get: obj => obj.applyLens } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _removeLens_decorators, { kind: "method", name: "removeLens", static: false, private: false, access: { has: obj => "removeLens" in obj, get: obj => obj.removeLens } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _play_decorators, { kind: "method", name: "play", static: false, private: false, access: { has: obj => "play" in obj, get: obj => obj.play } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _pause_decorators, { kind: "method", name: "pause", static: false, private: false, access: { has: obj => "pause" in obj, get: obj => obj.pause } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _mute_decorators, { kind: "method", name: "mute", static: false, private: false, access: { has: obj => "mute" in obj, get: obj => obj.mute } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _unmute_decorators, { kind: "method", name: "unmute", static: false, private: false, access: { has: obj => "unmute" in obj, get: obj => obj.unmute } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _setSource_decorators, { kind: "method", name: "setSource", static: false, private: false, access: { has: obj => "setSource" in obj, get: obj => obj.setSource } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _setFPSLimit_decorators, { kind: "method", name: "setFPSLimit", static: false, private: false, access: { has: obj => "setFPSLimit" in obj, get: obj => obj.setFPSLimit } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _setScreenRegions_decorators, { kind: "method", name: "setScreenRegions", static: false, private: false, access: { has: obj => "setScreenRegions" in obj, get: obj => obj.setScreenRegions } }, null, _instanceExtraInitializers); __esDecorate(_a, null, _destroy_decorators, { kind: "method", name: "destroy", static: false, private: false, access: { has: obj => "destroy" in obj, get: obj => obj.destroy } }, null, _instanceExtraInitializers); })(), _a; })(); export { CameraKitSession }; export const cameraKitSessionFactory = Injectable("CameraKitSession", [ lensCoreFactory.token, logEntriesFactory.token, lensKeyboardFactory.token, sessionStateFactory.token, lensStateFactory.token, pageVisibilityFactory.token, frameEventsFactory.token, ], (lensCore, logEntries, keyboard, sessionState, lensState, pageVisibility, frameEvents) => new CameraKitSession(keyboard, lensCore, sessionState, lensState, logEntries, pageVisibility, frameEvents)); //# sourceMappingURL=CameraKitSession.js.map