senza-sdk 0.0.356
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/bundle.js +1 -0
- package/dist/bundle.js.LICENSE.txt +3 -0
- package/dist/bundle.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Senza SDK
|
|
2
|
+
|
|
3
|
+
## About
|
|
4
|
+
|
|
5
|
+
You can use this SDK to integrate with the Synamedia Senza video streaming platform. To learn more about Senza and sign up for a developer account, visit https://senza.synamedia.com.
|
|
6
|
+
|
|
7
|
+
## Documentation
|
|
8
|
+
|
|
9
|
+
Once you have signed up for a developer account, you can access the developer documentation portal at https://developer.synamedia.com/senza.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
- npm: `npm install senza-sdk`
|
|
14
|
+
- yarn: `yarn add senza-sdk`
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
Your app should import and call `init()` to initialize the Senza SDK and `uiReady()` when your user interface is ready.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
import { init, uiReady } from "senza-sdk";
|
|
22
|
+
|
|
23
|
+
window.addEventListener("load", async () => {
|
|
24
|
+
try {
|
|
25
|
+
await init();
|
|
26
|
+
// set up your app
|
|
27
|
+
uiReady();
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error(e);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
See the documentation above for full integration instructions, sample code and tutorials.
|
package/dist/bundle.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.senza=t():e.senza=t()}(this,(()=>(()=>{"use strict";var e={d:(t,n)=>{for(var i in n)e.o(n,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:n[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{ClientAssertionError:()=>M,ConnectReason:()=>$,alarmManager:()=>S,auth:()=>N,deviceManager:()=>h,envInfo:()=>x,getClientAssertion:()=>z,getConnectReason:()=>L,getDeviceInfo:()=>Q,getPlatformInfo:()=>R,getTriggerEvent:()=>P,init:()=>q,isRunningE2E:()=>J,lifecycle:()=>c,messageManager:()=>b,remotePlayer:()=>p,setTimezone:()=>X,uiReady:()=>D,writeLicenseResponse:()=>U});var n={};e.r(n),e.d(n,{ClientAssertionError:()=>M,ConnectReason:()=>$,alarmManager:()=>S,auth:()=>N,deviceManager:()=>h,envInfo:()=>x,getClientAssertion:()=>z,getConnectReason:()=>L,getDeviceInfo:()=>Q,getPlatformInfo:()=>R,getTriggerEvent:()=>P,init:()=>q,isRunningE2E:()=>J,lifecycle:()=>c,messageManager:()=>b,remotePlayer:()=>p,setTimezone:()=>X,uiReady:()=>D,writeLicenseResponse:()=>U});const i={version:"3.20.6"},{version:s}=i;function o(){return Math.round(1e5*Math.random())+"-"+R().sessionInfo?.connectionId}class r{constructor(e){this.logFields=e}debug(...e){console.debug(this.formatLogString(e))}log(...e){console.log(this.formatLogString(e))}info(...e){console.info(this.formatLogString(e))}warn(...e){console.warn(this.formatLogString(e))}error(...e){console.error(this.formatLogString(e))}withFields(e){return new r({...this.logFields,...e})}formatLogString(e){let t="[hs-sdk] "+e.join(" ");return this.logFields&&(t+=" [log-fields] "+JSON.stringify(this.logFields)),t}}const a=new r({sdkVersion:s,url:window?.location?.href??""}),d=new class{sessionInfoStr="{}";get sessionInfoObj(){try{return JSON.parse(this.sessionInfoStr)}catch(e){return void a.warn("Failed to return sdk")}}setSessionInfoStr(e){try{JSON.parse(e)}catch(e){throw Error("Failed to parse sessionInfo")}this.sessionInfoStr=e}};class l extends EventTarget{constructor(){super(),"undefined"!=typeof document&&document.addEventListener("hs/uistatechange",(e=>{a.log("Got hs/uistatechange",e.detail);const t=new Event("onstatechange");t.state=e.detail,this.dispatchEvent(t)}))}getState(){if(window.cefQuery)return new Promise(((e,t)=>{window.cefQuery&&window.cefQuery({request:"uiState",persistent:!1,onSuccess:t=>{a.log(`uiState request successfully returned '${t}'`),e(t)},onFailure:(e,n)=>{a.error(`uiState request failed: ${e} ${n}`),t(n)}})}));a.warn("lifecycle getState is not supported if NOT running e2e")}moveToForeground(){if(window.cefQuery){const e=o(),t=a.withFields({FCID:e});t.log("lifecycle moveToForeground: sending uiActiveRequest action"),window.cefQuery({request:JSON.stringify({action:"uiActiveRequest",fcid:e}),persistent:!1,onSuccess:()=>{t.log("uiActiveRequest successfully sent")},onFailure:(e,n)=>{t.error(`uiActiveRequest failed: ${e} ${n}`)}})}else a.error("lifecycle moveToForeground: window.cefQuery is undefined")}moveToBackground(){if(window.cefQuery){const e=o(),t=a.withFields({FCID:e});t.log("lifecycle moveToBackground: sending play action"),window.cefQuery({request:JSON.stringify({action:"play",fcid:e}),persistent:!1,onSuccess:()=>{t.log("[ moveToBackground ] play successfully sent")},onFailure:(e,n)=>{t.error(`[ moveToBackground ] play failed: ${e} ${n}`)}})}else a.error("lifecycle moveToBackground: window.cefQuery is undefined")}switchTenant(e){if(e&&e.length>0){if(e===R().sessionInfo?.tenantId)return a.warn(`SwitchTenant requires a different tenantId than the current one. CurrentTenantId=${R().sessionInfo?.tenantId} and tenantId=${e}`),Promise.reject("SwitchTenant requires a different tenantId than the current one");const t=R().sessionInfo?.homeSessionInfo?.tenantInfo?.contentHubTenantId,n=R().sessionInfo?.homeSessionInfo?.tenantId;return a.log(`SwitchTenant for ${e}`),window.cefQuery?new Promise(((i,s)=>{const r=o(),d=a.withFields({FCID:r}),l={type:"reconnect",fcid:r,session:btoa(JSON.stringify({tenantId:e,...R().sessionInfo?.tenantId===t&&e!==n&&{returnToTenantId:t}}))},c={target:"TC",waitForResponse:!1,message:JSON.stringify(l)};window.cefQuery({request:JSON.stringify(c),persistent:!1,onSuccess:()=>{d.log("SwitchTenant request successfully sent"),i(!0)},onFailure:(e,t)=>{d.error(`SwitchTenant failed: ${e} ${t}`),s(`SwitchTenant failed: ${e} ${t}`)}})})):(a.warn("SwitchTenant is not supported if NOT running e2e"),Promise.reject("SwitchTenant is not supported if NOT running e2e"))}return a.warn("SwitchTenant requires a valid tenantId string parameter"),Promise.reject("SwitchTenant requires a valid tenantId string parameter")}exitApplication(){return window.cefQuery?new Promise(((e,t)=>{const n=o(),i=a.withFields({FCID:n});let s,r;const l=d.sessionInfoObj;l?.homeSessionInfo&&(l?.returnToTenantId||l?.homeSessionInfo.tenantId!==l?.tenantId)?(r={type:"reconnect",splashUrl:l?.homeSessionInfo.tenantInfo.tenantSettings.applicationSwitchSplashUrl,fcid:n},l?.returnToTenantId&&(l?.returnToTenantId===l?.homeSessionInfo.tenantInfo.contentHubTenantId&&(r.splashUrl=l?.homeSessionInfo.contentHubTenantInfo.tenantSettings.applicationSwitchSplashUrl),r.session=btoa(JSON.stringify({tenantId:l?.returnToTenantId}))),s={target:"TC",waitForResponse:!1,message:JSON.stringify(r)}):(r={type:"launchHomeApplication",fcid:n},s={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(r)}),window.cefQuery({request:JSON.stringify(s),persistent:!1,onSuccess:()=>{i.log(`exitApplication request with type: '${r.type}' successfully sent`),e(!0)},onFailure:(e,n)=>{i.error(`exitApplication request with type: '${r.type}' failed: ${e} ${n}`),t(`exitApplication request with type: '${r.type}' failed: ${e} ${n}`)}})})):(a.warn("exitApplication is not supported if NOT running e2e"),Promise.reject("exitApplication is not supported if NOT running e2e"))}}const c=new l,u=e=>JSON.parse(JSON.stringify(e));class f extends Error{constructor(e,t){super(t),this.code=e,this.msg=t}}function g(){const e=window.getPlaybackInfo?window.getPlaybackInfo():JSON.stringify({playbackPosition:0,assetDuration:0});let t;try{t=JSON.parse(e)}catch(n){a.error(`Playback Info parse failed. playbackStr = ${e}`),t={playbackPosition:0,assetDuration:0}}return t}class y extends EventTarget{constructor(){super(),this._config={preferredAudioLanguage:"",preferredSubtitlesLanguage:""},this._selectedAudioTrack="",this._selectedSubtitlesTrack="",this._availableAudioTracks=[],this._availableTextTracks=[],this._textTrackVisibility=!1,this._ptsSessionId=0,this._videoElement=void 0,this._isInitialized=!1,"undefined"!=typeof document&&document.addEventListener("hs/playbackInfoEvent",(()=>{a.info("Got hs/playbackInfoEvent"),this.dispatchEvent(new Event("timeupdate"))})),"undefined"!=typeof document&&document.addEventListener("hs/playback",(e=>{a.info("Got hs/playback event with detail",JSON.stringify(e?.detail)),this._availabilityStartTime=e?.detail?.availabilityStartTime,this._updateTracks(e?.detail),this.dispatchEvent(new Event("tracksupdate"))})),"undefined"!=typeof document&&document.addEventListener("EOS",(()=>{a.info("Got EOS event"),this.dispatchEvent(new Event("ended"))})),"undefined"!=typeof document&&document.addEventListener("hs/EOS",(()=>{a.info("Got hs/EOS event"),this.dispatchEvent(new Event("ended"))})),"undefined"!=typeof document&&document.addEventListener("hs/ui_inactive",(()=>{a.info("Got hs/ui_inactive event")})),"undefined"!=typeof document&&document.addEventListener("hs/senzaPlayerSetRate",(e=>{this._videoElement&&(this._videoElement.playbackRate=e.detail.rate)})),"undefined"!=typeof document&&document.addEventListener("ERR",(e=>{delete e?.detail?.type,delete e?.detail?.eventCode,a.info("Got ERR event",JSON.stringify(e?.detail)),this.dispatchEvent(new CustomEvent("error",e))})),"undefined"!=typeof document&&document.addEventListener("hs/ERR",(e=>{a.info("Got hs/ERR event"),delete e?.detail?.type,delete e?.detail?.eventCode,this.dispatchEvent(new CustomEvent("error",e))})),"undefined"!=typeof document&&document.addEventListener("hs/getLicense",(e=>{a.info("Got hs/getLicense event");const t=e?.detail,n=Uint8Array.from(t.request,(e=>e.charCodeAt(0))),i=new ArrayBuffer(n.byteLength);new Uint8Array(i).set(n),this.licenseRequest=i;const s=t.fcid,o=t.sessionId,r=new CustomEvent("license-request",{detail:{licenseRequest:i}});r.writeLicenseResponse=(e,t)=>{U(e,t,s,o)},this.dispatchEvent(r)}))}LoadMode=Object.freeze({NOT_LOADED:"notLoaded",LOADING:"loading",LOADED:"loaded"});async _init(e,t){let n={isLoaded:!1,playbackUrl:""};if(window.cefQuery){const e=o(),t=a.withFields({FCID:e}),i={type:"playerState",fcid:e},s={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(i)};try{const e=await new Promise(((e,n)=>{window.cefQuery({request:JSON.stringify(s),persistent:!1,onSuccess:n=>{t.log("playerState request successfully returned",n),e(n)},onFailure:(e,i)=>{t.error(`playerState request failed: ${e} ${i}`),n()}})}));n=JSON.parse(e)}catch{t.error("either failed to get or failed to parse player state")}}this._loadMode=n?.isLoaded?this.LoadMode.LOADED:this.LoadMode.NOT_LOADED,this._loadedUrl=n?.playbackUrl||"",this._isInitialized=!0,this._setPlayableUriTimeout=e?.setPlayableUriTimeout??5e3,this._requestVideoFrameInfo=e?.requestVideoFrameInfo??!0;let i={};try{i=JSON.parse(t?.playbackMetadata||"{}")}catch(e){a.error(`failed to parse playbackMetadata: ${e.message}`)}this._availabilityStartTime=i.availabilityStartTime,this._updateTracks(i)}_updateTracks(e){if(this._availableAudioTracks=e?.availableAudioTracks||this._availableAudioTracks,this._availableTextTracks=e?.availableSubtitlesTracks||this._availableTextTracks,"VOD"===e?.assetType&&(this._availableTextTracks=function(e){if(!e||e.length<1)return e;e.sort(((e,t)=>e.lang.toLowerCase()>t.lang.toLowerCase()?1:-1));const t=[{lang:"af",id:"*:af"},{lang:"ar",id:"*:ar"},{lang:"az",id:"*:az"},{lang:"bg",id:"*:bg"},{lang:"bs",id:"*:bs"},{lang:"ca",id:"*:ca"},{lang:"cs",id:"*:cs"},{lang:"cy",id:"*:cy"},{lang:"da",id:"*:da"},{lang:"de",id:"*:de"},{lang:"el",id:"*:el"},{lang:"en",id:"*:en"},{lang:"es",id:"*:es"},{lang:"es-MX",id:"*:es-MX"},{lang:"et",id:"*:et"},{lang:"fi",id:"*:fi"},{lang:"fr",id:"*:fr"},{lang:"fr-CA",id:"*:fr-CA"},{lang:"ga",id:"*:ga"},{lang:"ha",id:"*:ha"},{lang:"he",id:"*:he"},{lang:"hr",id:"*:hr"},{lang:"ht",id:"*:ht"},{lang:"hu",id:"*:hu"},{lang:"id",id:"*:id"},{lang:"is",id:"*:is"},{lang:"it",id:"*:it"},{lang:"kk",id:"*:kk"},{lang:"lt",id:"*:lt"},{lang:"lv",id:"*:lv"},{lang:"mk",id:"*:mk"},{lang:"mn",id:"*:mn"},{lang:"ms",id:"*:ms"},{lang:"mt",id:"*:mt"},{lang:"nl",id:"*:nl"},{lang:"no",id:"*:no"},{lang:"pl",id:"*:pl"},{lang:"pt",id:"*:pt"},{lang:"pt-PT",id:"*:pt-PT"},{lang:"ro",id:"*:ro"},{lang:"ru",id:"*:ru"},{lang:"sk",id:"*:sk"},{lang:"sl",id:"*:sl"},{lang:"so",id:"*:so"},{lang:"sq",id:"*:sq"},{lang:"sr",id:"*:sr"},{lang:"sv",id:"*:sv"},{lang:"sw",id:"*:sw"},{lang:"tl",id:"*:tl"},{lang:"tr",id:"*:tr"},{lang:"uk",id:"*:uk"},{lang:"uz",id:"*:uz"},{lang:"vi",id:"*:vi"},{lang:"zh",id:"*:zh"}],n=[...e];for(const i of t)e.find((e=>e.lang===i.lang))||(i.autoTranslate=!0,n.push(i));return n}(this._availableTextTracks)),this._availableAudioTracks){const e=this._availableAudioTracks.find((e=>!0===e.selected));this._selectedAudioTrack=e?.id||""}if(this._availableTextTracks){const e=this._availableTextTracks.find((e=>!0===e.selected));e?(this._selectedSubtitlesTrack=e.id,this._textTrackVisibility=!0):(this._selectedSubtitlesTrack="",this._textTrackVisibility=!1)}}getConfiguration(){return u(this._config)}configure(e){Object.entries(e).forEach((([e,t])=>{void 0!==this._config[e]&&(this._config[e]=t)}))}_changeLoadMode(e){this._loadMode!==e&&(this._loadMode=e,this.dispatchEvent(new Event("onloadmodechange")))}_handle_video_frame_info(e){if(!this._requestVideoFrameInfo||void 0===e)return void(this._videoElement=void 0);const t=o(),n=a.withFields({fcid:t}),i=(e,n)=>{const s={type:"currentFramePTS",fcid:t,currentFramePTS:n.mediaTime.toString(),ptsSessionId:this._ptsSessionId},o={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(s)};window.cefQuery({request:JSON.stringify(o),persistent:!1}),this._videoElement?.requestVideoFrameCallback(i)};n.log("handle_video_frame_pts: requesting video frame info"),void 0!==this._videoElement&&this._videoElement===e||(e.requestVideoFrameCallback(i),e.addEventListener("loadstart",(e=>{this._ptsSessionId++,a.info("videoElement, loadstart ptsSessionId=",this._ptsSessionId," event=",e)}))),this._videoElement=e}_reset(){this._availableAudioTracks=[],this._availableTextTracks=[],this._selectedAudioTrack="",this._selectedSubtitlesTrack="",this._availabilityStartTime=void 0}registerVideoElement(e){this._handle_video_frame_info(e)}async load(e,t){if(!this._isInitialized)throw new f(6500,"Cannot call load() if remote player is not initialized");if(e&&window.cefQuery){const n=await c.getState();if("background"===n||"inTransitionToBackground"===n)throw new f(6002,"Cannot call load() while in state 'background' or 'inTransitionToBackground'");if(this._loadMode===this.LoadMode.LOADING)throw new f(6501,"Cannot call load() while previous load is still in progress");this._reset();const i=this._loadMode;return this._changeLoadMode(this.LoadMode.LOADING),new Promise(((n,s)=>{this.currentTime=0;const r=o(),d=t??0,l=a.withFields({FCID:r,loadUrl:e,playbackPosition:d});l.log("remotePlayer load: sending setPlayableUri request");const c={type:"setPlayableUri",url:e,timeout:this._setPlayableUriTimeout,autoPlay:!1,playbackPosition:d,fcid:r},u={target:"TC",waitForResponse:!0,message:JSON.stringify(c)};let g=0;const y=Date.now(),p=window.cefQuery({request:JSON.stringify(u),persistent:!1,onSuccess:()=>{const i=Date.now()-y;l.withFields({duration:i}).log(`setPlayableUri completed successfully after ${i} ms`),t>0&&(this.currentTime=t),g&&(clearTimeout(g),g=0),this._changeLoadMode(this.LoadMode.LOADED),this._loadedUrl=e,n()},onFailure:(e,t)=>{const n=Date.now()-y;l.withFields({duration:n}).log(`setPlayableUri failed after ${n} ms. Error code: ${e}, error message: ${t}`),g&&(clearTimeout(g),g=0),99===e?this._changeLoadMode(i):(this._changeLoadMode(this.LoadMode.NOT_LOADED),this._loadedUrl=""),s(new f(e,t))}});l.log(`window.cefQuery for setPlayableUri returned query id ${p}`);const w=this._setPlayableUriTimeout+1e3;g=setTimeout((()=>{l.log(`setPlayableUri reached timeout of ${w} ms, canceling query id ${p}`),window.cefQueryCancel(p),this._changeLoadMode(this.LoadMode.NOT_LOADED),this._loadedUrl="",s(new f(6e3,`load reached timeout of ${w} ms`))}),w,p)}))}a.error("remotePlayer load: either window.cefQuery or url is undefined")}unload(){a.warn("unload() api is deprecated since version 3.14.0, no need to call unload() anymore at the end of playback")}play(e=!0){if(!this._isInitialized)throw new f(6500,"Cannot call play() if remote player is not initialized");if(window.cefQuery){if(this._loadMode!==this.LoadMode.LOADED)throw new f(6001,"Cannot call play() if player is not loaded");const t=o(),n=a.withFields({FCID:t});n.log("remotePlayer play: sending play action");const i=this._selectedAudioTrack||this._config.preferredAudioLanguage||"";let s="";if(this._textTrackVisibility&&(s=this._selectedSubtitlesTrack||this._config.preferredSubtitlesLanguage||""),e)window.cefQuery({request:JSON.stringify({action:"play",fcid:t,audioLanguage:i,subtitlesLanguage:s}),persistent:!1,onSuccess:()=>{n.log("play action was successfully sent")},onFailure:(e,t)=>{n.log(`failed to send play action: ${e} ${t}`)}});else{const e={type:"remotePlayer.play",class:"remotePlayer",action:"play",fcid:t,audioLanguage:i,subtitlesLanguage:s,playbackPosition:this.currentTime},o={target:"TC",waitForResponse:!1,message:JSON.stringify(e)};window.cefQuery({request:JSON.stringify(o),persistent:!1,onSuccess:()=>{n.log("remotePlayer play request successfully sent")},onFailure:(e,t)=>{n.error(`remotePlayer play request failed: ${e} ${t}`)}})}}else a.error("remotePlayer play: window.cefQuery is undefined")}pause(){if(!this._isInitialized)throw new f(6500,"Cannot call pause() if remote player is not initialized");if(window.cefQuery){if(this._loadMode!==this.LoadMode.LOADED)throw new f(6001,"Cannot call pause() if player is not loaded");const e=o(),t=a.withFields({FCID:e});t.log("remotePlayer pause: sending pause request");const n={type:"remotePlayer.pause",class:"remotePlayer",action:"pause",fcid:e},i={target:"TC",waitForResponse:!1,message:JSON.stringify(n)};window.cefQuery({request:JSON.stringify(i),persistent:!1,onSuccess:()=>{t.log("remotePlayer pause request successfully sent")},onFailure:(e,n)=>{t.error(`remotePlayer pause request failed: ${e} ${n}`)}})}else a.error("remotePlayer pause: window.cefQuery is undefined")}getAssetUri(){if(!this._isInitialized)throw new f(6500,"Cannot call getAssetUri() if remote player is not initialized");return this._loadedUrl}getLoadMode(){if(!this._isInitialized)throw new f(6500,"Cannot call getLoadMode() if remote player is not initialized");return this._loadMode}getTextTracks(){return u(this._availableTextTracks)}getAudioTracks(){return u(this._availableAudioTracks)}selectAudioTrack(e){for(const t of this.getAudioTracks())if(t.id===e)return void(this._selectedAudioTrack=e);a.warn(`Invalid audioTrackId ${e}`)}selectTextTrack(e){for(const t of this.getTextTracks())if(t.id===e)return void(this._selectedSubtitlesTrack=e);a.warn(`Invalid textTrackId ${e}`)}setTextTrackVisibility(e){const t=this._textTrackVisibility;if("boolean"!=typeof e)throw new TypeError("visible parameter must be a boolean");const n=e;n!==t&&(this._textTrackVisibility=n,n||(this._selectedSubtitlesTrack=""))}get currentTime(){return g()?.playbackPosition}set currentTime(e){!function(e){try{const t=JSON.stringify(e);window.setPlaybackInfo&&window.setPlaybackInfo(t)}catch(e){a.error("Playback Info to json string failed")}}({playbackPosition:e})}get duration(){return g()?.assetDuration}get textTrackVisibility(){return this._textTrackVisibility}getPresentationStartTimeAsDate(){return void 0===this._availabilityStartTime?null:new Date(1e3*this._availabilityStartTime)}}const p=new y;"undefined"!=typeof window&&(window.remotePlayer=p);const w={};class m extends EventTarget{constructor(){super(),w.level=0,w.quality=0,w.ssid="unknown",w.bssid="unknown","undefined"!=typeof document&&document.addEventListener("wifiSignalReport",(e=>{a.log("Got wifiSignalReport",JSON.stringify(e.detail)),w.level=e.detail.level,w.quality=e.detail.quality,w.ssid=e.detail.ssid,w.bssid=e.detail.bssid,this.dispatchEvent(new Event("wifiInfoUpdated"))}))}get deviceInfo(){const e=d.sessionInfoObj;return J()&&e?{deviceId:e.deviceId,connectionId:e.connectionId,community:e.community,tenant:e.tenant,clientIp:e.clientIp,countryCode:e.general?.location?.["x-country-code"]}:(a.log("getDeviceInfo running locally, returning dummy info"),{deviceId:"123456789",connectionId:"dummy",community:"LocalDev",tenant:"XXXXXX",clientIp:"0.0.0.0",countryCode:"XX"})}get wifiInfo(){return w}reboot(){return new Promise(((e,t)=>{if(window.cefQuery){const n=o(),i=a.withFields({FCID:n}),s={type:"reboot",fcid:n},r={target:"TC",waitForResponse:!1,message:JSON.stringify(s)};window.cefQuery({request:JSON.stringify(r),persistent:!1,onSuccess:()=>{i.log("reboot request successfully sent"),e(!0)},onFailure:(e,n)=>{i.error(`reboot failed: ${e} ${n}`),t(`reboot failed: ${e} ${n}`)}})}else a.warn("reboot is not supported if NOT running e2e"),t("reboot is not supported if NOT running e2e")}))}clearWifi(){return new Promise(((e,t)=>{const n=o(),i=a.withFields({FCID:n}),s={type:"resetWifi",fcid:n},r={target:"TC",waitForResponse:!1,message:JSON.stringify(s)};window.cefQuery({request:JSON.stringify(r),persistent:!1,onSuccess:()=>{i.log("clearWifi successfully sent"),e(!0)},onFailure:(e,n)=>{i.error(`clearWifi failed: ${e} ${n}`),t(`clearWifi failed: ${e} ${n}`)}})}))}sendDataToDevice(e){if("string"!=typeof e)throw new Error("data must be of type 'string'");return new Promise(((t,n)=>{const i=o(),s=a.withFields({FCID:i}),r={type:"externalCommand",data:{command:"forward",payload:e},fcid:i},d={target:"TC",waitForResponse:!1,message:JSON.stringify(r)};window.cefQuery({request:JSON.stringify(d),persistent:!1,onSuccess:()=>{s.log("externalCommand successfully sent"),t()},onFailure:(e,t)=>{s.error(`externalCommand failed: ${e} ${t}`),n(`externalCommand failed: ${e} ${t}`)}})}))}async factoryReset(e=!0){if("boolean"!=typeof e)throw new Error("reboot param must be of type 'boolean'");return new Promise(((t,n)=>{const i=o(),s=a.withFields({FCID:i}),r={type:"factoryReset",fcid:i,reboot:e},d={target:"TC",waitForResponse:!0,message:JSON.stringify(r)};let l=0;const c=window.cefQuery({request:JSON.stringify(d),persistent:!1,onSuccess:()=>{l&&clearTimeout(l),s.log("factoryReset successfully sent"),t(!0)},onFailure:(e,t)=>{l&&clearTimeout(l),s.error(`factoryReset failed: ${e} ${t}`),n(`factoryReset failed: ${e} ${t}`)}});l=setTimeout((()=>{s.error("factoryReset failed: reached timeout of 5000 ms"),window.cefQueryCancel(c),n("factoryReset failed: reached timeout of 5000 ms")}),5e3)}))}}const h=new m;class v extends EventTarget{constructor(){super(),"undefined"!=typeof document&&document.addEventListener("hs/alarmFiredEvent",(e=>{a.log("Got hs/alarmFiredEvent",JSON.stringify(e.detail)),e.detail?.alarmName&&this.dispatchEvent(new CustomEvent(e.detail.alarmName,{detail:e.detail.payload}))}))}addAlarm(e,t,n){if("string"!=typeof n)throw Error("data must be a string");const i=o(),s=a.withFields({alarmName:e,FCID:i});if(s.log(`addAlarm called for ${e} to be fired at ${t}`),window.cefQuery){const o={type:"addAlarm",fcid:i,alarmName:e,alarmTime:t,payload:n},r={target:"TC",waitForResponse:!1,message:JSON.stringify(o)};window.cefQuery({request:JSON.stringify(r),persistent:!1,onSuccess:()=>{s.log("addAlarm request successfully sent")},onFailure:(e,t)=>{s.error(`addAlarm failed: ${e} ${t}`)}})}else s.warn("addAlarm is not supported if NOT running e2e")}deleteAlarm(e){const t=o(),n=a.withFields({alarmName:e,FCID:t});if(n.log(`deleteAlarm called for ${e}`),window.cefQuery){const i={type:"deleteAlarm",fcid:t,alarmName:e},s={target:"TC",waitForResponse:!1,message:JSON.stringify(i)};window.cefQuery({request:JSON.stringify(s),persistent:!1,onSuccess:()=>{n.log("deleteAlarm request successfully sent")},onFailure:(e,t)=>{n.error(`deleteAlarm failed: ${e} ${t}`)}})}else n.warn("deleteAlarm is not supported if NOT running e2e")}deleteAllAlarms(){if(window.cefQuery){const e=o(),t=a.withFields({FCID:e}),n={type:"deleteAllAlarms",fcid:e},i={target:"TC",waitForResponse:!1,message:JSON.stringify(n)};window.cefQuery({request:JSON.stringify(i),persistent:!1,onSuccess:()=>{t.log("deleteAllAlarms request successfully sent")},onFailure:(e,n)=>{t.error(`deleteAllAlarms failed: ${e} ${n}`)}})}else a.warn("deleteAllAlarms is not supported if NOT running e2e")}getActiveAlarms(){throw Error("NOT IMPLEMENTED")}}const S=new v;"undefined"!=typeof window&&(window.alarmManager=S);class T extends EventTarget{constructor(){super(),"undefined"!=typeof document&&document.addEventListener("hs/externalEvent",(e=>{a.log("Got hs/externalEvent",JSON.stringify(e.detail)),this.dispatchEvent(new CustomEvent("message",{detail:{eventName:e.detail.eventName,payload:e.detail.payload,fcid:e.detail.fcid}}))}))}async registerGroups(e){return a.log(`register called for ${e}`),new Promise(((t,n)=>{if(window.cefQuery){const i=o(),s=a.withFields({FCID:i}),r={type:"registerGroupEvent",fcid:i,groups:e},d={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(r)};window.cefQuery({request:JSON.stringify(d),persistent:!1,onSuccess:()=>{s.log("registerGroupEvent request successfully sent"),t(!0)},onFailure:(e,t)=>{s.error(`registerGroupEvent failed: ${e} ${t}`),n(`registerGroupEvent failed: ${e} ${t}`)}})}else a.warn("registerGroupEvent is not supported if NOT running e2e"),n("registerGroupEvent is not supported if NOT running e2e")}))}}const b=new T;let I,k;"undefined"!=typeof window&&(window.messageManager=b),c.getState()?.then((e=>{k=e})),c.addEventListener("onstatechange",(e=>{k=e.state}));const E=e=>{"background"!==k&&"inTransitionToBackground"!==k||(I&&clearTimeout(I),I=setTimeout((()=>{"background"!==k&&"inTransitionToBackground"!==k||a.log(`${e.type} event received while in '${k}' state and there was no call to lifecycle.moveToForeground() for 500 ms. Make sure to call it if you want to move to foreground.`),I=0}),500))};"undefined"!=typeof document&&document.addEventListener("keydown",E),p.addEventListener("error",E),p.addEventListener("ended",E);const{version:_}=i;let O;const F="1.0";"undefined"!=typeof document&&document.addEventListener("keydown",(e=>{a.log(`Got ${e.key} key`)}));const N={getToken:async function(){return O?Promise.resolve(O):(a.log("getToken wait for promise updateSession event"),new Promise((e=>{document.addEventListener("updateSession",(t=>{O=t.detail?.updateObj,a.log(`onUpdateSessionEvent: token= ${O}`),e(O)}),{once:!0})})))},forceTokenUpdate:function(){if(O=null,window.cefQuery){const e=o(),t=a.withFields({FCID:e});t.log("forceTokenUpdate: sending updateSessionRequest");const n={type:"updateSessionRequest",updateKey:"authorization",parentPath:"settings.webUI.backendHeaders.Authorization",fcid:e},i={target:"TC",waitForResponse:!1,message:JSON.stringify(n)};window.cefQuery({request:JSON.stringify(i),persistent:!1,onSuccess:()=>{t.log("updateSessionRequest successfully sent")},onFailure:(e,n)=>{t.error(`updateSessionRequest failed: ${e} ${n}`)}})}else a.error("forceTokenUpdate: window.cefQuery is undefined")},getClientAssertion:z},$=Object.freeze({UNKNOWN:"unknown",INITIAL_CONNECTION:"initial_connection",UI_RELEASE:"ui_release",UI_TERMINATION:"ui_termination",WEBRTC_ERROR:"webrtc_error",UI_WATCHDOG:"ui_watchdog"});let C=$.UNKNOWN,A={};async function q(){if(a.log(`init ${_}`),window.diagnostics||a.error("[ init ] window.diagnostics is undefined"),window.cefQuery){await new Promise(((e,t)=>{window.cefQuery({request:"apiVersion "+F,persistent:!1,onSuccess:()=>{a.log("api version compatability check succeeded"),e()},onFailure:(e,n)=>{a.error("api version compatability check failed: "+n),t(n)}})}));const e=await new Promise((e=>{window.cefQuery({request:"sessionInfo",persistent:!1,onSuccess:t=>{a.log("sessionInfo request successfully returned "+t),e(t)},onFailure:(e,t)=>{a.error(`sessionInfo request failed: ${e} ${t}`)}})}));d.setSessionInfoStr(e);const t=JSON.parse(e);O=t?.settings?.webUI?.backendHeaders?.Authorization,a.log(`authToken: token = ${O}`),document.addEventListener("updateSession",(e=>{O=e.detail?.updateObj,a.log(`onUpdateSessionEvent: token = ${O}`)})),t?.settings?.["ui-streamer"]?.enableKeyPressDuration&&function(){const e=document.createElement("div");e.setAttribute("style","height: 8px; width: 8px; background-color: red; position: absolute; left: 0px; top: 0px; z-index: 9999;"),document.body.appendChild(e),document.addEventListener("keydown",(()=>{"red"===e.style.backgroundColor?e.style.backgroundColor="blue":"blue"===e.style.backgroundColor?e.style.backgroundColor="green":e.style.backgroundColor="red"}))}(),C=await new Promise((e=>{const t=o(),n=a.withFields({FCID:t}),i={type:"connectReason",fcid:t},s={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(i)};window.cefQuery({request:JSON.stringify(s),persistent:!1,onSuccess:t=>{n.log(`connectReason request successfully returned '${t}'`),e(t)},onFailure:(t,i)=>{n.error(`connectReason request failed: ${t} ${i}`),e($.UNKNOWN)}})}));const n=await new Promise((e=>{const t=o(),n=a.withFields({FCID:t}),i={type:"triggerEvent",fcid:t},s={target:"UI-Streamer",waitForResponse:!1,message:JSON.stringify(i)};window.cefQuery({request:JSON.stringify(s),persistent:!1,onSuccess:t=>{n.log(`triggerEvent request successfully returned '${t}'`),e(t)},onFailure:(t,i)=>{n.error(`triggerEvent request failed: ${t} ${i}`),e("")}})}));A={};let i={};if(n)try{i=JSON.parse(n),A.type=i.type,"keyPressEvent"===A.type?A.data={keyValue:i.keyValue}:"alarmFiredEvent"===A.type?A.data={alarmName:i.alarmName,payload:i.payload}:"userAlertEvent"===A.type?A.data={eventCode:i.eventCode,message:i.message}:"externalEvent"===A.type?A.data={eventName:i.eventName,payload:i.payload}:"videoPlaybackEvent"===A.type?A.data={eventCode:i.eventCode,errorCode:i.errorCode}:a.warn("unknown trigger event type",A.type)}catch(e){a.error(`failed to parse trigger event string ${n}: ${e.message}`)}await p._init(t?.settings?.["ui-streamer"],i)}else O=R().sessionInfo?.settings?.webUI?.backendHeaders?.Authorization,a.log(`authToken dummy: token = ${O}`);window.auth=N,window.close=()=>{a.warn("window.close is disabled on Senza platform. Use lifecycle.exitApplication() instead.")}}function L(){return C}function P(){return A}function R(){if("undefined"==typeof window||!window.diagnostics)return"undefined"==typeof window||window.diagnostics||a.error("[ getPlatformInfo ] window.diagnostics is undefined"),{version:"X.X.XX-X",pod:"ui-streamer-X.X.XX-X-QWERT-ASDFG-XXX-XXXXXX-XXXXX",podIP:"0.0.0.0",sessionInfo:{userAgent:"SynamediaSenza/XX.YY.ZZ",connectionId:"dummy",deviceId:"123456789",community:"LocalDev",tenant:"XXXXXX",tenantId:"XXXXXX",manifest:{transcontainer:"X.X.XX-X"},settings:{webUI:{backendHeaders:{Authorization:"Bearer dummytoken"}}},homeSessionInfo:{tenantId:"XXXXXX",community:"LocalDev"}}};try{const e=window.diagnostics()||{};return e.sessionInfo=d.sessionInfoObj,e}catch(e){a.error("Could not get platform info",e.stack)}}function X(e){if(window.cefQuery){const t={message:JSON.stringify({type:"setTimeZone",timezone:e}),waitForResponse:!1,target:"UI-Streamer"};window.cefQuery({request:JSON.stringify(t),persistent:!1,onSuccess:()=>{a.log("timezome is successfully set to",e)},onFailure:(t,n)=>{a.error(`error occurred setting timezone to ${e}: ${t} ${n}`)}})}}function J(){return!("undefined"==typeof window||!window.cefQuery)}function D(){window.cefQuery?window.cefQuery({request:"uiReady",persistent:!1,onSuccess:()=>{a.log("uiReady request successfully sent")},onFailure:(e,t)=>{a.error(`uiReady request failed: ${e} ${t}`)}}):a.error("uiReady: window.cefQuery is undefined")}function Q(){const e=d.sessionInfoObj;return J()?{deviceId:e.deviceId,connectionId:e.connectionId,community:e.community,tenant:e.tenant,clientIp:e.clientIp}:(a.log("getDeviceInfo running locally, returning dummy info"),{deviceId:"123456789",connectionId:"dummy",community:"LocalDev",tenant:"XXXXXX",clientIp:"0.0.0.0"})}const x={remoteBrowserIp:window.diagnostics?window.diagnostics().podIP:"127.0.0.1",sdkVersion:_};function U(e,t,n,i){if(200===e&&(t=window.btoa(String.fromCharCode.apply(null,new Uint8Array(t)))),window.cefQuery){const s={type:"updateLicense",sessionId:i,fcid:n};s[200===e?"response":"error"]=t;const o={target:"TC",waitForResponse:!1,message:JSON.stringify(s)};window.cefQuery({request:JSON.stringify(o),persistent:!1,onSuccess:()=>{a.log("updateLicense request successfully sent")},onFailure:(e,t)=>{a.error(`updateLicense request failed: ${e} ${t}`)}})}}class M extends Error{constructor(e,t){super(t),this.code=e}}function z(){if(window.cefQuery)return a.log("getClientAssertion is called"),new Promise(((e,t)=>{window.cefQuery({request:"client_assertion",persistent:!1,onSuccess:n=>{try{const t=JSON.parse(n);a.log(`client_assertion request successfully returned ${n}`),e(t)}catch(e){a.error(`Failed to parse client assertion ${n}`),t(new M(0,"Failed to parse client assertion"))}},onFailure:(e,n)=>{a.log(`client_assertion request failed: ${e} ${n}`),t(new M(e,n))}})}));a.warn("getClientAssertion is not supported if NOT running e2e")}return"undefined"!=typeof window&&(window.hs=n),t})()));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","mappings":"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","sources":["webpack://senza/webpack/universalModuleDefinition","webpack://senza/webpack/bootstrap","webpack://senza/webpack/runtime/define property getters","webpack://senza/webpack/runtime/hasOwnProperty shorthand","webpack://senza/webpack/runtime/make namespace object","webpack://senza/./src/utils.js","webpack://senza/./src/SessionInfo.js","webpack://senza/./src/lifecycle.js","webpack://senza/./src/remotePlayer.js","webpack://senza/./src/subtitlesUtils.js","webpack://senza/./src/deviceManager.js","webpack://senza/./src/alarmManager.js","webpack://senza/./src/messageManager.js","webpack://senza/./src/devHelper.js","webpack://senza/./src/api.js","webpack://senza/./src/keyPressIndicator.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"senza\"] = factory();\n\telse\n\t\troot[\"senza\"] = factory();\n})(this, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { getPlatformInfo } from \"./api\";\nimport pack from \"../package.json\";\nconst { version } = pack;\n\nexport function getFCID() {\n return Math.round(Math.random() * 100000) + \"-\" + getPlatformInfo().sessionInfo?.connectionId;\n}\n\n/* eslint-disable no-console */\nclass SdkLogger {\n\n constructor(logFields) {\n this.logFields = logFields;\n }\n debug(...data) {\n console.debug(this.formatLogString(data));\n }\n log(...data) {\n console.log(this.formatLogString(data));\n }\n info(...data) {\n console.info(this.formatLogString(data));\n }\n warn(...data) {\n console.warn(this.formatLogString(data));\n }\n error(...data) {\n console.error(this.formatLogString(data));\n }\n withFields(logFields) {\n return new SdkLogger({...this.logFields, ...logFields});\n }\n formatLogString(data) {\n let logString = \"[hs-sdk] \" + data.join(\" \");\n if (this.logFields) {\n logString += \" [log-fields] \" + JSON.stringify(this.logFields);\n }\n return logString;\n }\n}\n\nexport const sdkLogger = new SdkLogger({sdkVersion: version, url: window?.location?.href ?? \"\"});\n","import {sdkLogger} from \"./utils\";\n\nclass SessionInfo {\n sessionInfoStr= \"{}\";\n\n get sessionInfoObj() {\n try {\n return JSON.parse(this.sessionInfoStr);\n } catch (e) {\n sdkLogger.warn(\"Failed to return sdk\");\n return undefined;\n }\n\n }\n setSessionInfoStr(objStr) {\n try {\n JSON.parse(objStr); // Performing parse just as a validation that this is a valid json\n } catch (e) {\n throw Error(\"Failed to parse sessionInfo\");\n }\n\n this.sessionInfoStr = objStr;\n }\n}\n\nexport const sessionInfo = new SessionInfo();\n","import { getPlatformInfo } from \"./api\";\nimport { getFCID, sdkLogger } from \"./utils\";\nimport {sessionInfo} from \"./SessionInfo\";\n\n\n/**\n * 1. 'foreground' - ui is displayed<br>\n * 2. 'inTransitionToForeground' - ui is about to be displayed<br>\n * 3. 'background' - remote player is playing (full screen playback is displayed)<br>\n * 4. 'inTransitionToBackground' - remote player is about to be playing\n * @typedef {string} State\n */\n\n/**\n * Lifecycle is a singleton class that manages the application lifecycle states:<br>\n * @fires onstatechange\n */\nclass Lifecycle extends EventTarget {\n /**\n * onstatechange event.\n *\n * @event Lifecycle#onstatechange\n * @description Fired after transition from one state to another.<br>\n * The flow is: foreground --> inTransitionToBackground --> background --> inTransitionToForeground --> foreground\n * @property {State} state - Indicates the new state.\n * @example\n * lifecycle.addEventListener(\"onstatechange\", (e) => {\n * console.log(\"new state is\", e.state);\n * });\n */\n constructor() {\n super();\n typeof document !== \"undefined\" && document.addEventListener(\"hs/uistatechange\", (e) => {\n sdkLogger.log(\"Got hs/uistatechange\", e.detail);\n const event = new Event(\"onstatechange\");\n event.state = e.detail;\n this.dispatchEvent(event);\n });\n }\n\n /**\n * Async function that returns the ui lifecycle state\n * @returns {State} the current application lifecycle state\n * @example\n * try {\n * const state = await lifecycle.getState();\n * console.log(\"current state is\", state);\n * } catch (e) {\n * console.error(\"getState failed\", e);\n * }\n */\n getState() {\n if (window.cefQuery) {\n return new Promise((resolve, reject) => {\n window.cefQuery && window.cefQuery({\n request: \"uiState\",\n persistent: false,\n onSuccess: (response) => {\n sdkLogger.log(`uiState request successfully returned '${response}'`);\n resolve(response);\n },\n onFailure: (code, msg) => {\n sdkLogger.error(`uiState request failed: ${code} ${msg}`);\n reject(msg);\n }\n });\n });\n }\n sdkLogger.warn(\"lifecycle getState is not supported if NOT running e2e\");\n }\n\n /**\n * Once playback starts on the remote player,\n * the application is moved from foreground to inTransitionToBackground and eventually to background.\n * The application will need to call moveToForeground when it receives an event that needs the UI to be displayed again,\n * for example a key press, a playback end-of-file or a playback error.\n */\n moveToForeground() {\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n logger.log(\"lifecycle moveToForeground: sending uiActiveRequest action\");\n window.cefQuery({\n request: JSON.stringify({ action: \"uiActiveRequest\", fcid: FCID }),\n persistent: false,\n onSuccess: () => {\n logger.log(\"uiActiveRequest successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`uiActiveRequest failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.error(\"lifecycle moveToForeground: window.cefQuery is undefined\");\n }\n }\n\n /**\n * @experimental\n * Once playback starts on the local player (i.e UI)\n * The method moves the application to background.\n * if the objective is to move the UI explicitly to background\n * The method is called after remotePlayer.play(false)\n * @example\n * remotePlayer.load(\"https://example.com/video.mp4\", 0);\n * remotePlayer.play(false);\n * lifecycle.moveToBackground();\n */\n moveToBackground() {\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n logger.log(\"lifecycle moveToBackground: sending play action\");\n window.cefQuery({\n request: JSON.stringify({ action: \"play\", fcid: FCID }),\n persistent: false,\n onSuccess: () => {\n logger.log(\"[ moveToBackground ] play successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`[ moveToBackground ] play failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.error(\"lifecycle moveToBackground: window.cefQuery is undefined\");\n }\n }\n\n /** Switch Tenant\n * Use this api to switch to another tenant (other than the home tenant) which will launch the application associated with the tenantId. The tenantId must be configured in the\n * Senza platform. Switching to the home tenant should use the exitApplication().\n * @param {string} tenantId The tenantId to switch\n * @return {Promise} Promise which is resolved when the switchTenant command has been successfully processed.\n * Failure to process the switchTenant command will result in the promise being rejected.\n */\n switchTenant(tenantId) {\n if (tenantId && tenantId.length > 0) {\n if (tenantId === getPlatformInfo().sessionInfo?.tenantId) {\n sdkLogger.warn(`SwitchTenant requires a different tenantId than the current one. CurrentTenantId=${getPlatformInfo().sessionInfo?.tenantId} and tenantId=${tenantId}`);\n return Promise.reject(\"SwitchTenant requires a different tenantId than the current one\");\n }\n\n // TODO: Need to discuss checking for a valid tenantId in the Senza platform\n const contentHubTenantId = getPlatformInfo().sessionInfo?.homeSessionInfo?.tenantInfo?.contentHubTenantId;\n const homeTenantId = getPlatformInfo().sessionInfo?.homeSessionInfo?.tenantId;\n sdkLogger.log(`SwitchTenant for ${tenantId}`);\n if (window.cefQuery) {\n return new Promise((resolve, reject) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = {\n type: \"reconnect\",\n fcid: FCID,\n session: btoa(JSON.stringify({tenantId,\n ...getPlatformInfo().sessionInfo?.tenantId === contentHubTenantId && tenantId !== homeTenantId && {returnToTenantId: contentHubTenantId}}))\n };\n const request = {target: \"TC\", waitForResponse: false, message: JSON.stringify(message)};\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"SwitchTenant request successfully sent\");\n resolve(true);\n },\n onFailure: (code, msg) => {\n logger.error(`SwitchTenant failed: ${code} ${msg}`);\n reject(`SwitchTenant failed: ${code} ${msg}`);\n }\n });\n });\n }\n sdkLogger.warn(\"SwitchTenant is not supported if NOT running e2e\");\n return Promise.reject(\"SwitchTenant is not supported if NOT running e2e\");\n }\n sdkLogger.warn(\"SwitchTenant requires a valid tenantId string parameter\");\n return Promise.reject(\"SwitchTenant requires a valid tenantId string parameter\");\n }\n\n /** Exit Application\n * Use this api to exit the application which will redirect the browser to the home tenant application.\n * @return {Promise} Promise which is resolved when the exitApplication command has been successfully processed.\n * Failure to process the exitApplication command will result in the promise being rejected.\n */\n exitApplication() {\n if (window.cefQuery) {\n return new Promise((resolve, reject) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n let request;\n let message;\n const sessionInfoObj = sessionInfo.sessionInfoObj;\n // Checking homeSessionInfo exists for backward compatibility\n if (sessionInfoObj?.homeSessionInfo && (sessionInfoObj?.returnToTenantId || sessionInfoObj?.homeSessionInfo.tenantId !== sessionInfoObj?.tenantId)) {\n message = {\n type: \"reconnect\",\n splashUrl: sessionInfoObj?.homeSessionInfo.tenantInfo.tenantSettings.applicationSwitchSplashUrl,\n fcid: FCID\n };\n if (sessionInfoObj?.returnToTenantId) {\n if (sessionInfoObj?.returnToTenantId === sessionInfoObj?.homeSessionInfo.tenantInfo.contentHubTenantId) {\n message.splashUrl = sessionInfoObj?.homeSessionInfo.contentHubTenantInfo.tenantSettings.applicationSwitchSplashUrl;\n }\n message.session = btoa(JSON.stringify({tenantId: sessionInfoObj?.returnToTenantId}));\n }\n request = {target: \"TC\", waitForResponse: false, message: JSON.stringify(message)};\n } else {\n message = {\n type: \"launchHomeApplication\",\n fcid: FCID\n };\n request = {target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message)};\n }\n\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(`exitApplication request with type: '${message.type}' successfully sent`);\n resolve(true);\n },\n onFailure: (code, msg) => {\n logger.error(`exitApplication request with type: '${message.type}' failed: ${code} ${msg}`);\n reject(`exitApplication request with type: '${message.type}' failed: ${code} ${msg}`);\n }\n });\n });\n }\n sdkLogger.warn(\"exitApplication is not supported if NOT running e2e\");\n return Promise.reject(\"exitApplication is not supported if NOT running e2e\");\n }\n}\n\n/**\n *\n * @module\n * @example\n * import { lifecycle } from \"senza-sdk\";\n *\n * @return {Lifecycle} pointer to the Lifecycle singleton\n */\nexport const lifecycle = new Lifecycle();\n","\nimport { getFCID, sdkLogger } from \"./utils\";\nimport { lifecycle } from \"./lifecycle\";\nimport { writeLicenseResponse } from \"./api\";\nimport { mergeAutoTranslationLanguages } from \"./subtitlesUtils\";\n\nconst INVALID_SET_PLAYABLE_URI_CODE = 99;\nconst DEFAULT_SET_PLAYABLE_URI_TIMEOUT = 5000;\n\nconst cloneDeep = (element) => {\n return JSON.parse(JSON.stringify(element));\n};\n\n/** Error object to be thrown on remotePlayer api failures.\n * Possible error codes:\n *\n * | Error Code | Description |\n * | :--------- | :---------------------------------------------------------------------------------------------- |\n * | 6000 | The call to load() has reached the configurable timeout with no response from the remote player |\n * | 6001 | play() was called while the remote player is not loaded |\n * | 6002 | load() was called while the application was in state 'background' or 'inTransitionToBackground' |\n * | 6500 | remotePlayer api was called before initializing remotePlayer |\n * | 6501 | load() was called while previous load was still in progress |\n * | 23 | load() failed due to remote player initialization error |\n * | 98 | load() failed due to remote player failure to send message to the client |\n * | 99 | load() failed due to remote player reporting invalid message |\n * | 1000-1001 | load() failed due to remote player reporting CDM failure |\n */\nclass RemotePlayerError extends Error {\n constructor(code, message) {\n super(message);\n this.code = code;\n this.msg = message; // For backwards compatibility\n }\n}\n\nfunction getPlaybackInfo() {\n const playbackInfoStr = window.getPlaybackInfo ? window.getPlaybackInfo() : JSON.stringify({ playbackPosition: 0, assetDuration: 0 });\n let playbackInfo;\n try {\n playbackInfo = JSON.parse(playbackInfoStr);\n } catch (e) {\n sdkLogger.error(`Playback Info parse failed. playbackStr = ${playbackInfoStr}`);\n playbackInfo = { playbackPosition: 0, assetDuration: 0 };\n }\n\n return playbackInfo;\n}\n\nfunction setPlaybackInfo(playbackInfo) {\n try {\n const playbackInfoStr = JSON.stringify(playbackInfo);\n if (window.setPlaybackInfo) {\n window.setPlaybackInfo(playbackInfoStr);\n }\n } catch (e) {\n sdkLogger.error(\"Playback Info to json string failed\");\n }\n}\n\n/**\n* @typedef {Object} Config\n* @property {string} preferredAudioLanguage\n* @property {string} preferredSubtitlesLanguage\n*/\n\n/**\n * RemotePlayer a singleton class to communicate with remote player\n * @fires timeupdate\n * @fires tracksupdate\n * @fires ended\n * @fires error\n * @fires onloadmodechange\n */\nclass RemotePlayer extends EventTarget {\n constructor() {\n super();\n /**\n * @type {Config}\n * @private\n */\n this._config = {\n preferredAudioLanguage: \"\",\n preferredSubtitlesLanguage: \"\"\n };\n /**\n * @type {string}\n * @private\n */\n this._selectedAudioTrack = \"\";\n /**\n * @type {string}\n * @private\n */\n this._selectedSubtitlesTrack = \"\";\n /**\n * @type {AudioTrack[]}\n * @private\n */\n this._availableAudioTracks = [];\n /**\n * @type {TextTrack[]}\n * @private\n */\n this._availableTextTracks = [];\n\n /**\n * @type {boolean}\n * @private\n */\n this._textTrackVisibility = false;\n\n\n /**\n * @type {number}\n * @private\n */\n this._ptsSessionId = 0;\n\n this._videoElement = undefined;\n /**\n * @type {boolean}\n * @private\n */\n this._isInitialized = false;\n\n /**\n *\n * @event RemotePlayer#timeupdate\n * @example\n * remotePlayer.addEventListener(\"timeupdate\", () => {\n * console.info(\"remotePlayer timeupdate\", remotePlayer.currentTime);\n * localPlayer.getMediaElement().currentTime = remotePlayer.currentTime || 0;\n * });\n *\n */\n typeof document !== \"undefined\" && document.addEventListener(\"hs/playbackInfoEvent\", () => {\n sdkLogger.info(\"Got hs/playbackInfoEvent\");\n this.dispatchEvent(new Event(\"timeupdate\"));\n });\n\n /**\n *\n * @event RemotePlayer#tracksupdate\n * @example\n * remotePlayer.addEventListener(\"tracksupdate\", () => {\n * console.info(\"remotePlayer tracksupdate\", remotePlayer.getAudioTracks(), remotePlayer.getTextTracks());\n * });\n *\n */\n typeof document !== \"undefined\" && document.addEventListener(\"hs/playback\", (e) => {\n sdkLogger.info(\"Got hs/playback event with detail\", JSON.stringify(e?.detail));\n this._availabilityStartTime = e?.detail?.availabilityStartTime;\n this._updateTracks(e?.detail);\n this.dispatchEvent(new Event(\"tracksupdate\"));\n });\n\n /**\n * @event RemotePlayer#ended\n * @example\n * remotePlayer.addEventListener(\"ended\", () => {\n * console.info(\"remotePlayer ended\");\n * });\n */\n typeof document !== \"undefined\" && document.addEventListener(\"EOS\", () => {\n sdkLogger.info(\"Got EOS event\");\n this.dispatchEvent(new Event(\"ended\"));\n });\n // we will remove the listener to EOS once ui-streamer will send hs/EOS\n typeof document !== \"undefined\" && document.addEventListener(\"hs/EOS\", () => {\n sdkLogger.info(\"Got hs/EOS event\");\n this.dispatchEvent(new Event(\"ended\"));\n });\n\n typeof document !== \"undefined\" && document.addEventListener(\"hs/ui_inactive\", () => {\n sdkLogger.info(\"Got hs/ui_inactive event\");\n });\n typeof document !== \"undefined\" && document.addEventListener(\"hs/senzaPlayerSetRate\", (event) => {\n if (this._videoElement) this._videoElement.playbackRate = event.detail.rate;\n });\n\n /**\n *\n * @event RemotePlayer#error\n * @type {object}\n * @property {int} detail.errorCode\n * @property {string} detail.message\n *\n * @see Possible error codes:\n *\n * | Code | Domain | Description |\n * | :-------- | :---------------- | :------------------------------------------------------------------------------------------- |\n * | 1000 | Encrypted content | Failed to create or initialise the CDM |\n * | 1001 | Encrypted content | Failed to create a CDM session |\n * | 1002 | Encrypted content | CDM failed to generate a license request |\n * | 1003 | Encrypted content | The CDM rejected the license server response |\n * | 1004 | Encrypted content | The CDM rejected the license server certificate |\n * | 1005 | Encrypted content | All keys in the license have expired |\n * | 1006 | Encrypted content | Output device is incompatible with the license requirements (HDCP) |\n * | 1007 | Encrypted content | The device has been revoked |\n * | 1008 | Encrypted content | The device secrets aren't available |\n * | 1999 | Encrypted content | An unknown encrypted content error |\n * | 2000 | Player | Content makes reference to no or unsupported key system |\n * | 3000 | Player | Unexpected problem with playback, only used if no more specific code in 3xxx range applies |\n * | 3001 | Player | Problem accessing content manifest, only used if no more specific code in 8xxx range applies |\n * | 3002 | Player | Unexpectedly stopped playback |\n * | 3100 | Player | Problem parsing MP4 content |\n * | 3200 | Player | Problem with decoder |\n * | 3300 | Player | DRM keys unavailable, player waited for keys but none arrived |\n * | 3400 | Player | Problem accessing segments, only used if no more specific code in 34xx range applies |\n * | 3401 | Player | Problem accessing segments, connection issue or timeout |\n * | 3402 | Player | Problem accessing segments, server returned HTTP error code |\n * | 3403 | Player | Problem accessing segments, server authentication issue |\n * | 3404 | Player | Problem accessing segments, server returned not found |\n * | 3900-3999 | Player | Internal player error |\n * | 8001 | Player | Error pulling manifest. bad parameters |\n * | 8002 | Player | Error pulling manifest. filters returned no data |\n * | 8003 | Player | Error pulling manifest. fetch error |\n * | 8004 | Player | Error pulling manifest. parse error |\n * | 8005 | Player | Error pulling manifest. stale manifest detected |\n * | 8006 | Player | Error updating manifest. internal cache error |\n * | 8007 | Player | Error updating manifest. internal error during backoff |\n * | 8008 | Player | Error pulling manifest. sidx parsing error |\n * | 8009 | Player | Error pulling manifest. internal error |\n *\n * @example\n * remotePlayer.addEventListener(\"error\", (event) => {\n * console.error(\"received remotePlayer error:\", event.detail.errorCode, event.detail.message);\n * });\n *\n */\n typeof document !== \"undefined\" && document.addEventListener(\"ERR\", (event) => {\n delete event?.detail?.type; // type is always videoPlaybackEvent, so no need to pass it\n delete event?.detail?.eventCode; // eventCode is always ERR, so no need to pass it\n sdkLogger.info(\"Got ERR event\", JSON.stringify(event?.detail));\n this.dispatchEvent(new CustomEvent(\"error\", event));\n });\n // we will remove the listener to ERR once ui-streamer will send hs/ERR\n typeof document !== \"undefined\" && document.addEventListener(\"hs/ERR\", (event) => {\n sdkLogger.info(\"Got hs/ERR event\");\n delete event?.detail?.type; // type is always videoPlaybackEvent, so no need to pass it\n delete event?.detail?.eventCode; // eventCode is always ERR, so no need to pass it\n this.dispatchEvent(new CustomEvent(\"error\", event));\n });\n\n /**\n *\n * @event RemotePlayer#getLicense\n * @type {object}\n * @property {object} detail - object containing data related to the event:\n * sessionId, fcid, licenseRequest.\n * The 'hs/getLicense' event is fired from the platform when it (the platform) receives the license request.\n * after receiving the event, the function fires a 'license-request' event\n * with the contents of the 'hs/getLicense' event.\n * The 'hs/getLicense' request contains: fcid, sessionId, base64 encoded licenseRequest\n */\n typeof document !== \"undefined\" && document.addEventListener(\"hs/getLicense\", (event) => {\n sdkLogger.info(\"Got hs/getLicense event\");\n const getLicenseEventData = event?.detail;\n\n const buffer = Uint8Array.from(getLicenseEventData.request, (c) => c.charCodeAt(0));\n const licenseRequest = new ArrayBuffer(buffer.byteLength);\n new Uint8Array(licenseRequest).set(buffer);\n\n this.licenseRequest = licenseRequest;\n const fcid = getLicenseEventData.fcid;\n const sessionId = getLicenseEventData.sessionId;\n const licenseRequestEvent = new CustomEvent(\"license-request\", { \"detail\": { licenseRequest } });\n licenseRequestEvent.writeLicenseResponse = (statusCode, responseBody) => {\n writeLicenseResponse(statusCode, responseBody, fcid, sessionId);\n };\n this.dispatchEvent(licenseRequestEvent);\n });\n }\n\n /**\n * @typedef {Object} LoadMode\n * @property {string} NOT_LOADED\n * @property {string} LOADING\n * @property {string} LOADED\n */\n LoadMode = Object.freeze({\n NOT_LOADED: \"notLoaded\",\n LOADING: \"loading\",\n LOADED: \"loaded\"\n });\n\n /** @private Initialize the remote player\n * @param {Object} uiStreamerSettings ui-streamer portion of the settings taken from session info\n * */\n async _init(uiStreamerSettings, triggerEvent) {\n let playerState = {\n isLoaded: false,\n playbackUrl: \"\"\n };\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = {\n type: \"playerState\",\n fcid: FCID\n };\n const request = {target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message)};\n try {\n const playerStateStr = await new Promise((resolve, reject) => {\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: (playerState) => {\n logger.log(\"playerState request successfully returned\", playerState);\n resolve(playerState);\n },\n onFailure: (code, msg) => {\n logger.error(`playerState request failed: ${code} ${msg}`);\n reject();\n }\n });\n });\n playerState = JSON.parse(playerStateStr);\n } catch {\n logger.error(\"either failed to get or failed to parse player state\");\n }\n }\n this._loadMode = playerState?.isLoaded ? this.LoadMode.LOADED : this.LoadMode.NOT_LOADED;\n this._loadedUrl = playerState?.playbackUrl || \"\";\n this._isInitialized = true;\n this._setPlayableUriTimeout = uiStreamerSettings?.setPlayableUriTimeout ?? DEFAULT_SET_PLAYABLE_URI_TIMEOUT;\n this._requestVideoFrameInfo = uiStreamerSettings?.requestVideoFrameInfo ?? true;\n let playbackMetadata = {};\n try {\n playbackMetadata = JSON.parse(triggerEvent?.playbackMetadata || \"{}\");\n } catch (e) {\n sdkLogger.error(`failed to parse playbackMetadata: ${e.message}`);\n }\n this._availabilityStartTime = playbackMetadata.availabilityStartTime;\n this._updateTracks(playbackMetadata);\n }\n\n /** @private update audio and text tracks\n * @param {Object} playbackMetadata playback metadata that comes along the hs/playback event or trigger event\n * */\n _updateTracks(playbackMetadata) {\n this._availableAudioTracks = playbackMetadata?.availableAudioTracks || this._availableAudioTracks;\n this._availableTextTracks = playbackMetadata?.availableSubtitlesTracks || this._availableTextTracks;\n if (playbackMetadata?.assetType === \"VOD\") {\n this._availableTextTracks = mergeAutoTranslationLanguages(this._availableTextTracks);\n }\n if (this._availableAudioTracks) {\n const selectedTrack = this._availableAudioTracks.find((track) => track.selected === true);\n this._selectedAudioTrack = selectedTrack?.id || \"\";\n }\n if (this._availableTextTracks) {\n const selectedTrack = this._availableTextTracks.find((track) => track.selected === true);\n if (selectedTrack) {\n this._selectedSubtitlesTrack = selectedTrack.id;\n this._textTrackVisibility = true;\n } else {\n this._selectedSubtitlesTrack = \"\";\n this._textTrackVisibility = false;\n }\n }\n }\n\n /** get the player configuration.\n * @returns {Config}\n * */\n getConfiguration() {\n return cloneDeep(this._config);\n }\n\n /** setting values for properties in the player configuration using an object.\n * if the config does not support a property this is a no-op\n * @param {Object} props the object with all the different properties to change\n * @example\n * remotePlayer.configure({ preferredAudioLanguage: 'en-US' })\n *\n * */\n configure(props) {\n Object.entries(props).forEach(([key, value]) => {\n if (this._config[key] !== undefined) {\n this._config[key] = value;\n }\n });\n }\n\n /** @private change the internal load mode and dispatch the onloadmodechange event */\n _changeLoadMode(newLoadMode) {\n if (this._loadMode !== newLoadMode) {\n this._loadMode = newLoadMode;\n /**\n *\n * @event RemotePlayer#onloadmodechange\n * @example\n * remotePlayer.addEventListener(\"onloadmodechange\", () => {\n * console.info(\"remotePlayer load mode changed to\", remotePlayer.getLoadMode());\n * });\n *\n */\n this.dispatchEvent(new Event(\"onloadmodechange\"));\n }\n }\n\n /** @private manage getting the current video frame media time and sending to the platform until the sdk\n * receives the ui_inactive message from the platform\n * */\n _handle_video_frame_info(videoElement) {\n if (!this._requestVideoFrameInfo || videoElement === undefined) {\n this._videoElement = undefined;\n return;\n }\n\n const fcid = getFCID();\n const logger = sdkLogger.withFields({fcid});\n\n const videoFrameCallback = (now, metadata) => {\n const message = {\n type: \"currentFramePTS\",\n fcid: fcid,\n currentFramePTS: metadata.mediaTime.toString(),\n ptsSessionId: this._ptsSessionId\n };\n const request = {target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message)};\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false\n });\n\n this._videoElement?.requestVideoFrameCallback(videoFrameCallback);\n };\n\n logger.log(\"handle_video_frame_pts: requesting video frame info\");\n if (this._videoElement === undefined || this._videoElement !== videoElement) {\n videoElement.requestVideoFrameCallback(videoFrameCallback);\n videoElement.addEventListener(\"loadstart\", (event) => {\n this._ptsSessionId++;\n sdkLogger.info(\"videoElement, loadstart ptsSessionId=\", this._ptsSessionId, \" event=\", event);\n });\n }\n this._videoElement = videoElement;\n }\n\n _reset() {\n this._availableAudioTracks = [];\n this._availableTextTracks = [];\n this._selectedAudioTrack = \"\";\n this._selectedSubtitlesTrack = \"\";\n this._availabilityStartTime = undefined;\n }\n\n /** In order to support a seamless switch between the video in the UI and ABR, the web application must\n * register the video element being used for the currently played video before calling the load and play apis.\n * @param {object} video The video element currently playing video in the web application\n * */\n registerVideoElement(video) {\n this._handle_video_frame_info(video);\n }\n\n\n /** Tell the remote player to load the given URL\n * @param {string} url url to load\n * @param {number} [position] start position in seconds (if not provided, start from beginning (VOD) or current time (LTV))\n * @returns {Promise}\n * @throws {RemotePlayerError} error object contains code & msg\n *\n * */\n async load(url, position) {\n if (!this._isInitialized) {\n throw new RemotePlayerError(6500, \"Cannot call load() if remote player is not initialized\");\n }\n if (url && window.cefQuery) {\n const state = await lifecycle.getState();\n if (state === \"background\" || state === \"inTransitionToBackground\") {\n throw new RemotePlayerError(6002, \"Cannot call load() while in state 'background' or 'inTransitionToBackground'\");\n }\n if (this._loadMode === this.LoadMode.LOADING) {\n throw new RemotePlayerError(6501, \"Cannot call load() while previous load is still in progress\");\n }\n this._reset();\n const previousLoadMode = this._loadMode;\n this._changeLoadMode(this.LoadMode.LOADING);\n return new Promise((resolve, reject) => {\n // first, zero playback position\n this.currentTime = 0;\n const FCID = getFCID();\n const playbackPosition = position ?? 0;\n const logger = sdkLogger.withFields({FCID, loadUrl: url, playbackPosition});\n logger.log(\"remotePlayer load: sending setPlayableUri request\");\n const message = {\n type: \"setPlayableUri\",\n url,\n timeout: this._setPlayableUriTimeout,\n autoPlay: false,\n playbackPosition,\n fcid: FCID\n };\n const request = { target: \"TC\", waitForResponse: true, message: JSON.stringify(message) };\n let timerId = 0;\n const timeBeforeSendingRequest = Date.now();\n const queryId = window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n const duration = Date.now() - timeBeforeSendingRequest;\n logger.withFields({duration}).log(`setPlayableUri completed successfully after ${duration} ms`);\n if (position > 0) {\n this.currentTime = position;\n }\n if (timerId) {\n clearTimeout(timerId);\n timerId = 0;\n }\n this._changeLoadMode(this.LoadMode.LOADED);\n this._loadedUrl = url;\n resolve();\n },\n onFailure: (code, msg) => {\n const duration = Date.now() - timeBeforeSendingRequest;\n logger.withFields({duration}).log(`setPlayableUri failed after ${duration} ms. Error code: ${code}, error message: ${msg}`);\n if (timerId) {\n clearTimeout(timerId);\n timerId = 0;\n }\n // If setPlayableUri failed because the request was invalid, we want to retain the previous load mode\n if (code === INVALID_SET_PLAYABLE_URI_CODE) {\n this._changeLoadMode(previousLoadMode);\n } else {\n this._changeLoadMode(this.LoadMode.NOT_LOADED);\n this._loadedUrl = \"\";\n }\n reject(new RemotePlayerError(code, msg));\n }\n });\n logger.log(`window.cefQuery for setPlayableUri returned query id ${queryId}`);\n const loadTimeout = this._setPlayableUriTimeout + 1000;\n timerId = setTimeout(() => {\n logger.log(`setPlayableUri reached timeout of ${loadTimeout} ms, canceling query id ${queryId}`);\n window.cefQueryCancel(queryId);\n this._changeLoadMode(this.LoadMode.NOT_LOADED);\n this._loadedUrl = \"\";\n reject(new RemotePlayerError(6000, `load reached timeout of ${loadTimeout} ms`));\n }, loadTimeout, queryId);\n });\n }\n\n sdkLogger.error(\"remotePlayer load: either window.cefQuery or url is undefined\");\n }\n\n /** @deprecated since 3.14.0, no need to call unload() anymore at the end of playback.\n * */\n unload() {\n sdkLogger.warn(\"unload() api is deprecated since version 3.14.0, no need to call unload() anymore at the end of playback\");\n }\n\n\n /**\n * Play loaded URL. Assuming load was called before.\n * @experimental @param {boolean} [moveToBackground=true] if true, the UI will automatically move to background state\n * if false, the UI will remain in foreground state, need to call lifecycle.moveToBackground() to move to background\n * This is an experimental feature and may not work as expected\n * @example\n * remotePlayer.load(\"https://example.com/video.mp4\", 0);\n * remotePlayer.play(false);\n * lifecycle.moveToBackground();\n *\n * // if moveToBackground=true\n * remotePlayer.load(\"https://example.com/video.mp4\", 0);\n * remotePlayer.play();\n * @throws {RemotePlayerError} error object contains code & msg\n */\n play(moveToBackground = true) {\n if (!this._isInitialized) {\n throw new RemotePlayerError(6500, \"Cannot call play() if remote player is not initialized\");\n }\n if (window.cefQuery) {\n if (this._loadMode !== this.LoadMode.LOADED) {\n throw new RemotePlayerError(6001, \"Cannot call play() if player is not loaded\");\n }\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n logger.log(\"remotePlayer play: sending play action\");\n const audioLanguage = this._selectedAudioTrack || this._config.preferredAudioLanguage || \"\";\n let subtitlesLanguage = \"\";\n if (this._textTrackVisibility) {\n subtitlesLanguage = this._selectedSubtitlesTrack || this._config.preferredSubtitlesLanguage || \"\";\n }\n if (moveToBackground) {\n window.cefQuery({\n request: JSON.stringify({ action: \"play\", fcid: FCID, audioLanguage, subtitlesLanguage }),\n persistent: false,\n onSuccess: () => {\n logger.log(\"play action was successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.log(`failed to send play action: ${code} ${msg}`);\n }\n });\n } else {\n const message = {\n type: \"remotePlayer.play\",\n class: \"remotePlayer\",\n action: \"play\",\n fcid: FCID,\n audioLanguage,\n subtitlesLanguage,\n playbackPosition: this.currentTime\n };\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"remotePlayer play request successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`remotePlayer play request failed: ${code} ${msg}`);\n }\n });\n }\n } else {\n sdkLogger.error(\"remotePlayer play: window.cefQuery is undefined\");\n }\n }\n\n /** pauses the currently playing video\n * @throws {RemotePlayerError} error object contains code & msg\n *\n * */\n pause() {\n if (!this._isInitialized) {\n throw new RemotePlayerError(6500, \"Cannot call pause() if remote player is not initialized\");\n }\n if (window.cefQuery) {\n if (this._loadMode !== this.LoadMode.LOADED) {\n throw new RemotePlayerError(6001, \"Cannot call pause() if player is not loaded\");\n }\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n logger.log(\"remotePlayer pause: sending pause request\");\n const message = {\n type: \"remotePlayer.pause\",\n class: \"remotePlayer\",\n action: \"pause\",\n fcid: FCID\n };\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"remotePlayer pause request successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`remotePlayer pause request failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.error(\"remotePlayer pause: window.cefQuery is undefined\");\n }\n }\n\n /** get the currently loaded uri, or empty string is player is not loaded\n * @returns {string} loaded uri\n * @throws {RemotePlayerError} error object contains code & msg\n *\n * */\n getAssetUri() {\n if (!this._isInitialized) {\n throw new RemotePlayerError(6500, \"Cannot call getAssetUri() if remote player is not initialized\");\n }\n return this._loadedUrl;\n }\n\n /** get the current load mode (either NOT_LOADED or LOADING or LOADED)\n * @returns {LoadMode} current load mode\n * @throws {RemotePlayerError} error object contains code & msg\n * @example\n * import { remotePlayer } from \"senza-sdk\";\n * const loadMode = remotePlayer.getLoadMode();\n * if (loadMode === remotePlayer.LoadMode.LOADED) {\n * console.log(\"remote player is currently loaded\");\n * }\n *\n * */\n getLoadMode() {\n if (!this._isInitialized) {\n throw new RemotePlayerError(6500, \"Cannot call getLoadMode() if remote player is not initialized\");\n }\n return this._loadMode;\n }\n\n /**\n * @typedef {Object} TextTrack\n * @property {string} id - A unique ID for the track.\n * @property {string} lang - The track's language.\n * @property {boolean} selected - Whether the track is selected.\n * @property {boolean} autoTranslate - (Optional) Whether the track is an auto-translated language.\n */\n /** get all the text (subtitles) tracks\n * text tracks are available only after playing content and returning to the UI\n * when text tracks are updated, the @event tracksupdate if fired.\n * Auto Translation languages are returned only for VOD assets where there is at least one text track in the manifest to be used for translation.\n * The list of tracks is sorted ascending to two parts by the lang key in the following order:\n * 1. The actual text tracks which is available in the asset manifest and the selected track\n * 2. Auto-Translation tracks\n * @returns {TextTrack[]} an array of TextTracks if available, otherwise - empty array\n *\n * */\n getTextTracks() {\n return cloneDeep(this._availableTextTracks);\n }\n /**\n * @typedef {Object} AudioTrack\n * @property {string} id - A unique ID for the track.\n * @property {string} lang - The track's language.\n * @property {boolean} selected - Whether the track is selected.\n */\n /** get all the audio tracks\n * text tracks are available only after playing content and returning to the UI\n * when audio tracks are updated, teh @event tracksupdate is fired.\n * @returns {AudioTrack[]} an array of objects if available, otherwise - empty array\n *\n * */\n getAudioTracks() {\n return cloneDeep(this._availableAudioTracks);\n }\n /** Select a specific audio track.\n * track id should come from a call to getAudioTracks.\n * if no tracks exist - this is a no-op.\n * if the id does not match the id of any of the existing tracks - this is a no-op.\n * @param {string} audioTrackId the selected audio track id\n *\n * */\n selectAudioTrack(audioTrackId) {\n for (const track of this.getAudioTracks()) {\n if (track.id === audioTrackId) {\n this._selectedAudioTrack = audioTrackId;\n return;\n }\n }\n sdkLogger.warn(`Invalid audioTrackId ${audioTrackId}`);\n }\n /** Select a specific text (subtitle) track.\n * track id should come from a call to getTextTracks.\n * if no tracks exist - this is a no-op.\n * if the id does not match the id of any of the existing tracks - this is a no-op.\n * @param {string} textTrackId the selected text track id\n *\n * */\n selectTextTrack(textTrackId) {\n for (const track of this.getTextTracks()) {\n if (track.id === textTrackId) {\n this._selectedSubtitlesTrack = textTrackId;\n return;\n }\n }\n sdkLogger.warn(`Invalid textTrackId ${textTrackId}`);\n }\n\n /**\n * Enable or disable the subtitles.\n * if the player is in an unloaded state, the request will be applied next time content is played.\n * @param {boolean} visible whether the subtitles are visible or not\n * @throws {TypeError} if visible is not a boolean variable\n */\n setTextTrackVisibility(visible) {\n const oldVisibility = this._textTrackVisibility;\n if (typeof visible !== \"boolean\") {\n throw new TypeError(\"visible parameter must be a boolean\");\n }\n const newVisibility = visible;\n if (newVisibility === oldVisibility) {\n return;\n }\n this._textTrackVisibility = newVisibility;\n if (!newVisibility) {\n // Setting the visibility to false clears any previous selections user has done\n this._selectedSubtitlesTrack = \"\";\n }\n }\n\n /**\n * Getter/Setter for currentTime\n */\n get currentTime() {\n return getPlaybackInfo()?.playbackPosition;\n }\n set currentTime(playbackPosition) {\n setPlaybackInfo({ playbackPosition });\n }\n\n /**\n * For VOD asset, the duration of the asset\n * @readonly\n */\n get duration() {\n return getPlaybackInfo()?.assetDuration;\n }\n\n /**\n * Whether the subtitles are visible or not.\n * @readonly\n */\n get textTrackVisibility() {\n return this._textTrackVisibility;\n }\n\n /** Get the presentation start time as a date. This should only be called when the player has loaded a live stream.\n * If the player has not loaded a live stream, this will return null.\n * @returns {Date} presentation start time\n *\n * */\n getPresentationStartTimeAsDate() {\n if (this._availabilityStartTime === undefined) {\n return null;\n }\n return new Date(this._availabilityStartTime * 1000);\n }\n}\n/**\n *\n * @module\n * @example\n * import { init, remotePlayer } from \"senza-sdk\";\n * await init();\n * try {\n * await remotePlayer.load(\"http://playable.url/file.mp4\");\n * remotePlayer.play();\n * } catch(err) {\n * console.log(\"remotePlayer api failed with error code\", err.code, err.msg);\n * }\n *\n * @returns {RemotePlayer} pointer to the RemotePlayer singleton\n */\nexport const remotePlayer = new RemotePlayer();\n// Adding remotePlayer to window for testing purposes which allows us to use and test remotePlayer APIs in pipeline tests\nif (typeof window !== \"undefined\") {\n window.remotePlayer = remotePlayer;\n}\n","\n/**\n * Returns a list of auto translation supported subtitles\n * @returns {[{id: string, lang: string, autoTranslate: boolean}]}\n */\n\nexport function getAutoTranslationLanguages() {\n // KEEP THE LIST SORTED BY lang field\n return [\n {lang: \"af\", id: \"*:af\"},\n {lang: \"ar\", id: \"*:ar\"},\n {lang: \"az\", id: \"*:az\"},\n {lang: \"bg\", id: \"*:bg\"},\n {lang: \"bs\", id: \"*:bs\"},\n {lang: \"ca\", id: \"*:ca\"},\n {lang: \"cs\", id: \"*:cs\"},\n {lang: \"cy\", id: \"*:cy\"},\n {lang: \"da\", id: \"*:da\"},\n {lang: \"de\", id: \"*:de\"},\n {lang: \"el\", id: \"*:el\"},\n {lang: \"en\", id: \"*:en\"},\n {lang: \"es\", id: \"*:es\"},\n {lang: \"es-MX\",id: \"*:es-MX\"},\n {lang: \"et\", id: \"*:et\"},\n {lang: \"fi\", id: \"*:fi\"},\n {lang: \"fr\", id: \"*:fr\"},\n {lang: \"fr-CA\",id: \"*:fr-CA\"},\n {lang: \"ga\", id: \"*:ga\"},\n {lang: \"ha\", id: \"*:ha\"},\n {lang: \"he\", id: \"*:he\"},\n {lang: \"hr\", id: \"*:hr\"},\n {lang: \"ht\", id: \"*:ht\"},\n {lang: \"hu\", id: \"*:hu\"},\n {lang: \"id\", id: \"*:id\"},\n {lang: \"is\", id: \"*:is\"},\n {lang: \"it\", id: \"*:it\"},\n {lang: \"kk\", id: \"*:kk\"},\n {lang: \"lt\", id: \"*:lt\"},\n {lang: \"lv\", id: \"*:lv\"},\n {lang: \"mk\", id: \"*:mk\"},\n {lang: \"mn\", id: \"*:mn\"},\n {lang: \"ms\", id: \"*:ms\"},\n {lang: \"mt\", id: \"*:mt\"},\n {lang: \"nl\", id: \"*:nl\"},\n {lang: \"no\", id: \"*:no\"},\n {lang: \"pl\", id: \"*:pl\"},\n {lang: \"pt\", id: \"*:pt\"},\n {lang: \"pt-PT\",id: \"*:pt-PT\"},\n {lang: \"ro\", id: \"*:ro\"},\n {lang: \"ru\", id: \"*:ru\"},\n {lang: \"sk\", id: \"*:sk\"},\n {lang: \"sl\", id: \"*:sl\"},\n {lang: \"so\", id: \"*:so\"},\n {lang: \"sq\", id: \"*:sq\"},\n {lang: \"sr\", id: \"*:sr\"},\n {lang: \"sv\", id: \"*:sv\"},\n {lang: \"sw\", id: \"*:sw\"},\n {lang: \"tl\", id: \"*:tl\"},\n {lang: \"tr\", id: \"*:tr\"},\n {lang: \"uk\", id: \"*:uk\"},\n {lang: \"uz\", id: \"*:uz\"},\n {lang: \"vi\", id: \"*:vi\"},\n {lang: \"zh\", id: \"*:zh\"}\n ];\n}\n\nexport function mergeAutoTranslationLanguages(sourceLanguagesList) {\n\n if (!sourceLanguagesList || sourceLanguagesList.length < 1) {\n // Cannot translate to any language if there are no source subtitles to translate from\n return sourceLanguagesList;\n }\n // First, sort the source list by lang\n sourceLanguagesList.sort((a, b) => a.lang.toLowerCase() > b.lang.toLowerCase() ? 1 : -1);\n\n const translationLangs = getAutoTranslationLanguages();\n const mergedList = [... sourceLanguagesList];\n for (const tl of translationLangs) {\n if (sourceLanguagesList.find((lang) => lang.lang === tl.lang)) {\n // skip auto translation lang if the same lang already exist in sourceLanguageList\n continue;\n }\n tl.autoTranslate = true;\n mergedList.push(tl);\n }\n return mergedList;\n}\n","import { getFCID, sdkLogger } from \"./utils\";\nimport {isRunningE2E} from \"./api\";\nimport {sessionInfo} from \"./SessionInfo\";\n\nconst wifiInfo = {};\n\nconst FACTORY_RESET_TIMEOUT_SECONDS = 5;\n\n/**\n * DeviceManager is a singleton class that manages the device\n * @fires wifiInfoUpdated\n */\nclass DeviceManager extends EventTarget {\n\n constructor() {\n super();\n wifiInfo.level = 0;\n wifiInfo.quality = 0;\n wifiInfo.ssid = \"unknown\";\n wifiInfo.bssid = \"unknown\";\n /**\n *\n * @event DeviceManager#wifiInfoUpdated\n * @example\n * deviceManager.addEventListener(\"wifiInfoUpdated\", () => {\n * console.info(\"Wifi info has been updated to\", deviceManager.wifiInfo);\n * });\n *\n */\n typeof document !== \"undefined\" && document.addEventListener(\"wifiSignalReport\", (e) => {\n sdkLogger.log(\"Got wifiSignalReport\", JSON.stringify(e.detail));\n wifiInfo.level = e.detail.level;\n wifiInfo.quality = e.detail.quality;\n wifiInfo.ssid = e.detail.ssid;\n wifiInfo.bssid = e.detail.bssid;\n this.dispatchEvent(new Event(\"wifiInfoUpdated\"));\n });\n\n }\n\n /**\n * @property {object} DeviceInfo\n * @property {string} DeviceInfo.deviceId\n * @property {string} DeviceInfo.connectionId\n * @property {string} DeviceInfo.community\n * @property {string} DeviceInfo.tenant\n * @property {string} DeviceInfo.clientIp\n * @property {string} DeviceInfo.countryCode A 2-letter code as defined in ISO_3166-1\n */\n get deviceInfo() {\n const sessionInfoObj = sessionInfo.sessionInfoObj;\n if (isRunningE2E() && sessionInfoObj) {\n return {\n deviceId: sessionInfoObj.deviceId,\n connectionId: sessionInfoObj.connectionId,\n community: sessionInfoObj.community,\n tenant: sessionInfoObj.tenant,\n clientIp: sessionInfoObj.clientIp,\n countryCode: sessionInfoObj.general?.location?.[\"x-country-code\"]\n };\n }\n sdkLogger.log(\"getDeviceInfo running locally, returning dummy info\");\n return {\n deviceId: \"123456789\",\n connectionId: \"dummy\",\n community: \"LocalDev\",\n tenant: \"XXXXXX\",\n clientIp: \"0.0.0.0\",\n countryCode: \"XX\"\n };\n }\n\n /**\n * @property {object} WifiInfo\n * @property {number} WifiInfo.level\n * @property {number} WifiInfo.quality\n * @property {string} WifiInfo.ssid\n * @property {string} WifiInfo.bssid\n */\n get wifiInfo() {\n return wifiInfo;\n }\n\n /**\n * Reboot the device\n * @return {Promise} Promise which is resolved when the reboot command has been successfully processed.\n * Failure to process the reboot command will result in the promise being rejected.\n */\n reboot() {\n return new Promise((resolve, reject) => {\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({ FCID });\n const message = {\n type: \"reboot\",\n fcid: FCID\n };\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"reboot request successfully sent\");\n resolve(true);\n },\n onFailure: (code, msg) => {\n logger.error(`reboot failed: ${code} ${msg}`);\n reject(`reboot failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.warn(\"reboot is not supported if NOT running e2e\");\n reject(\"reboot is not supported if NOT running e2e\");\n }\n });\n }\n\n /**\n * Delete current wifi configuration and forget network\n * @return {Promise} Promise which is resolved when the clearWifi command has been successfully processed.\n * Failure to process the clearWifi command will result in the promise being rejected.\n */\n clearWifi() {\n return new Promise((resolve, reject) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({ FCID });\n const message = {\n type: \"resetWifi\",\n fcid: FCID\n };\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"clearWifi successfully sent\");\n resolve(true);\n },\n onFailure: (code, msg) => {\n logger.error(`clearWifi failed: ${code} ${msg}`);\n reject(`clearWifi failed: ${code} ${msg}`);\n }\n });\n });\n }\n\n /**\n * Send raw data directly to a customer's device via the USB serial connection of a Senza device.\n * This function is specifically designed for customers who have their devices connected to a Senza device.\n * Using this API, these customers can transmit messages or data directly to their connected devices.\n * The transmission occurs through the Senza device's USB serial interface, facilitating direct communication\n * between the customer's web application and their device.\n * @param {String} data raw data to be passed to the device\n * @return {Promise} Promise which is resolved when the command has been successfully processed.\n * Failure to process the command will result in the promise being rejected.\n */\n sendDataToDevice(data) {\n if (typeof data !== \"string\") {\n throw new Error(\"data must be of type 'string'\");\n }\n return new Promise((resolve, reject) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({ FCID });\n const message = {\n type: \"externalCommand\",\n data: {\n command: \"forward\",\n payload: data\n },\n fcid: FCID\n };\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"externalCommand successfully sent\");\n resolve();\n },\n onFailure: (code, msg) => {\n logger.error(`externalCommand failed: ${code} ${msg}`);\n reject(`externalCommand failed: ${code} ${msg}`);\n }\n });\n });\n }\n\n /**\n * Perform device factory reset.\n * @param {Boolean} [reboot=true] a flag that is passed to the device to indicate whether it should reboot after the factory reset. defaults to true.\n * @return {Promise} Promise which is resolved when factoryReset has been successfully performed\n * Failure to factoryReset for any reason, result in the promise being rejected.\n */\n async factoryReset(reboot = true) {\n if (typeof reboot !== \"boolean\") {\n throw new Error(\"reboot param must be of type 'boolean'\");\n }\n return new Promise((resolve, reject) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({ FCID });\n const message = {\n type: \"factoryReset\",\n fcid: FCID,\n reboot\n };\n const request = { target: \"TC\", waitForResponse: true, message: JSON.stringify(message) };\n let timeoutHandler = 0;\n const queryId = window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n if (timeoutHandler) {\n clearTimeout(timeoutHandler);\n }\n logger.log(\"factoryReset successfully sent\");\n resolve(true);\n },\n onFailure: (code, msg) => {\n if (timeoutHandler) {\n clearTimeout(timeoutHandler);\n }\n logger.error(`factoryReset failed: ${code} ${msg}`);\n reject(`factoryReset failed: ${code} ${msg}`);\n }\n });\n\n timeoutHandler = setTimeout(() => {\n logger.error(`factoryReset failed: reached timeout of ${FACTORY_RESET_TIMEOUT_SECONDS * 1000} ms`);\n window.cefQueryCancel(queryId);\n reject(`factoryReset failed: reached timeout of ${FACTORY_RESET_TIMEOUT_SECONDS * 1000} ms`);\n }, FACTORY_RESET_TIMEOUT_SECONDS * 1000);\n });\n }\n}\n\n/**\n *\n * @module\n * @example\n * import { deviceManager } from \"senza-sdk\";\n * console.info(deviceManager.wifiInfo.ssid)\n * await deviceManager.clearWifi()\n * deviceManager.reboot()\n *\n * @return {DeviceManager} pointer to the DeviceManager singleton\n */\nexport const deviceManager = new DeviceManager();\n","\nimport {getFCID,sdkLogger} from \"./utils\";\n\n/**\n * AlarmManager is a singleton class that manages the alarms in the application. It fires events whose types are the names of the alarms.\n * @fires MyAlarm\n */\nclass AlarmManager extends EventTarget {\n\n /**\n * alarm event\n *\n * @event AlarmManager#MyAlarm\n * @description Fired when time of 'MyAlarm' arrives.<br>\n * @example\n * alarmManager.addEventListener(\"MyAlarm\", (e) => {\n * console.log(\"alarm MyAlarm arrived with data\", e.detail);\n * });\n * alarmManager.addAlarm(\"MyAlarm\", Date.now() + 60*60*1000, \"MyData\");\n */\n constructor() {\n super();\n typeof document !== \"undefined\" && document.addEventListener(\"hs/alarmFiredEvent\", (e) => {\n sdkLogger.log(\"Got hs/alarmFiredEvent\", JSON.stringify(e.detail));\n if (e.detail?.alarmName) {\n this.dispatchEvent(new CustomEvent(e.detail.alarmName, {detail: e.detail.payload }));\n }\n });\n }\n\n /** Set alarm to be fired at the specified time, event when ui is released\n * @param {string} alarmName unique name for the alarm\n * @param {number} alarmTime time for the alarm to be fired, represented by the number of milliseconds elapsed since the epoch\n * @param {string} [data] data to be passed back when the alarm is fired\n *\n * */\n addAlarm(alarmName, alarmTime, data) {\n if (typeof data !== \"string\") {\n throw Error(\"data must be a string\");\n }\n const FCID = getFCID();\n const logger = sdkLogger.withFields({alarmName, FCID});\n logger.log(`addAlarm called for ${alarmName} to be fired at ${alarmTime}`);\n if (window.cefQuery) {\n const message = {\n type: \"addAlarm\",\n fcid: FCID,\n alarmName,\n alarmTime,\n payload: data\n };\n const request = { target:\"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"addAlarm request successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`addAlarm failed: ${code} ${msg}`);\n }\n });\n } else {\n logger.warn(\"addAlarm is not supported if NOT running e2e\");\n }\n }\n\n /** Delete the specified alarm\n * @param {string} alarmName name of alarm to be deleted\n *\n * */\n deleteAlarm(alarmName) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({alarmName, FCID});\n logger.log(`deleteAlarm called for ${alarmName}`);\n if (window.cefQuery) {\n const message = {\n type: \"deleteAlarm\",\n fcid: FCID,\n alarmName\n };\n const request = { target:\"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"deleteAlarm request successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`deleteAlarm failed: ${code} ${msg}`);\n }\n });\n } else {\n logger.warn(\"deleteAlarm is not supported if NOT running e2e\");\n }\n }\n\n /** Delete all alarms\n *\n * */\n deleteAllAlarms() {\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = {\n type: \"deleteAllAlarms\",\n fcid: FCID\n };\n const request = { target:\"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"deleteAllAlarms request successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`deleteAllAlarms failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.warn(\"deleteAllAlarms is not supported if NOT running e2e\");\n }\n }\n\n /** Async function that asks for all active alarms\n * @returns {Promise} when resolved, returns an array of objects containing alarmName and alarmTime fields\n * @throws {string} error string in case of an error\n *\n * */\n getActiveAlarms() {\n throw Error(\"NOT IMPLEMENTED\");\n // if (window.cefQuery) {\n // const message = {\n // type: \"getActiveAlarms\",\n // fcid: getFCID()\n // };\n // const request = { target:\"TC\", waitForResponse: true, message: JSON.stringify(message) };\n // return new Promise((resolve, reject) => {\n // window.cefQuery && window.cefQuery({\n // request: JSON.stringify(request),\n // persistent: false,\n // onSuccess: (response) => {\n // console.log(`getActiveAlarms successfully returned ${response}`);\n // try {\n // resolve(JSON.parse(response));\n // } catch (e) {\n // reject(`failed to parse getActiveAlarms response ${response}`);\n // }\n // },\n // onFailure: (code, msg) => {\n // console.log(`getActiveAlarms failed: ${code} ${msg}`);\n // reject(msg);\n // }\n // });\n // });\n // }\n // console.warn(\"getActiveAlarms is not supported if NOT running e2e\");\n }\n}\n\n/**\n *\n * @module\n * @example\n * import { alarmManager } from \"senza-sdk\";\n *\n * @return {AlarmManager} pointer to the AlarmManager singleton\n */\nexport const alarmManager = new AlarmManager();\n// Adding alarm manager to window for testing purposes which allows us to use and test alarmManager APIs in pipeline tests\nif (typeof window !== \"undefined\") {\n window.alarmManager = alarmManager;\n}\n","\nimport {getFCID, sdkLogger} from \"./utils\";\n\n/**\n * MessageManager is a singleton class that manages the external messages received by the application. It fires custom events as \"message\" with the payload as the content\n * @fires MessageManager#message\n */\n\nclass MessageManager extends EventTarget {\n\n /**\n * @typedef {object} MessageDetails - object which contains the content of the message\n * @property {string} eventName - The name of the event message, a property of MessageDetails\n * @property {object} payload - The payload for this event, a property of MessageDetails\n * @property {string} fcid - The flow context for this message, a property of MessageDetails\n */\n\n /**\n * message event\n *\n * @event MessageManager#message\n * @type {CustomEvent}\n * @property {MessageDetails} detail - object containing data related to the event:\n\n *\n * @description Fired when an external event arrives. This is a generic handler for all messages received for any registered group <br>\n * @example\n * messageManager.addEventListener(\"message\", (e) => {\n * console.log(\"message arrived with data\", e.detail);\n * });\n *\n */\n constructor() {\n super();\n typeof document !== \"undefined\" && document.addEventListener(\"hs/externalEvent\", (e) => {\n sdkLogger.log(\"Got hs/externalEvent\", JSON.stringify(e.detail));\n this.dispatchEvent(new CustomEvent(\"message\", {detail: {eventName: e.detail.eventName, payload: e.detail.payload, fcid: e.detail.fcid } }));\n });\n }\n\n /** Register to specific group(s). This function replaces the previously registered groups\n * @param {Array<String>} groups group events to receive messages.\n * @return {Promise} Promise which is resolved when the registerGroups command has been successfully processed.\n * Failure to process the registerGroups command will result in the promise being rejected.\n * messageManager.registerGroups([\"A\",\"B\"]);\n * */\n async registerGroups(groups) {\n sdkLogger.log(`register called for ${groups}`);\n return new Promise((resolve, reject) => {\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = {\n type: \"registerGroupEvent\",\n fcid: FCID,\n groups\n };\n const request = {target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message)};\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"registerGroupEvent request successfully sent\");\n resolve(true);\n },\n onFailure: (code, msg) => {\n logger.error(`registerGroupEvent failed: ${code} ${msg}`);\n reject(`registerGroupEvent failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.warn(\"registerGroupEvent is not supported if NOT running e2e\");\n reject(\"registerGroupEvent is not supported if NOT running e2e\");\n }\n });\n }\n}\n\n/**\n *\n * @module\n * @example\n * import { MessageManager } from \"senza-sdk\";\n *\n * @return {MessageManager} pointer to the MessageManager singleton\n */\n\nexport const messageManager = new MessageManager();\n// Adding message manager to window for testing purposes which allows us to use and test messageManager APIs in pipeline tests\nif (typeof window !== \"undefined\") {\n window.messageManager = messageManager;\n}\n","import { lifecycle,remotePlayer } from \"./api\";\nimport { sdkLogger } from \"./utils\";\n\nconst timeout = 500;\nlet timerId;\nlet currentState;\n\nlifecycle.getState()?.then((state) => {\n currentState = state;\n});\n\nlifecycle.addEventListener(\"onstatechange\", (e) => {\n currentState = e.state;\n});\n\nconst handleHintLogging = (event) => {\n if (currentState === \"background\" || currentState === \"inTransitionToBackground\") {\n if (timerId) {\n clearTimeout(timerId);\n }\n timerId = setTimeout(() => {\n if (currentState === \"background\" || currentState === \"inTransitionToBackground\") {\n sdkLogger.log(`${event.type} event received while in '${currentState}' state and there was no call to lifecycle.moveToForeground() for ${timeout} ms. Make sure to call it if you want to move to foreground.`);\n }\n timerId = 0;\n }, timeout);\n }\n};\n\ntypeof document !== \"undefined\" && document.addEventListener(\"keydown\", handleHintLogging);\nremotePlayer.addEventListener(\"error\", handleHintLogging);\nremotePlayer.addEventListener(\"ended\", handleHintLogging);\n","import { enableKeyPressIndicator } from \"./keyPressIndicator\";\n\nimport { getFCID, sdkLogger } from \"./utils\";\nimport pack from \"../package.json\";\nimport {sessionInfo} from \"./SessionInfo\";\nconst { version } = pack;\n\nlet authToken;\n\nconst API_VERSION = \"1.0\";\n\ntypeof document !== \"undefined\" && document.addEventListener(\"keydown\", (event) => {\n sdkLogger.log(`Got ${event.key} key`);\n});\n\n/** @namespace auth\n *@example\n * import { auth } from \"senza-sdk\";\n **/\nexport const auth = {\n\n /** Should be called upon startup and be embedded in future requests */\n getToken,\n\n /** Should be called upon '401' event (unauthorized) */\n forceTokenUpdate,\n\n getClientAssertion\n\n};\n\n/**\n * @typedef {Object} ConnectReason - The reason the ui app has been loaded\n * @property {string} UNKNOWN\n * @property {string} INITIAL_CONNECTION - Indicates that ui app has been loaded for the first time\n * @property {string} UI_RELEASE - Indicates that ui app has been reloaded after ui release\n * @property {string} UI_TERMINATION - Indicates that ui app has been reloaded due to ui termination\n * @property {string} WEBRTC_ERROR - Indicates that ui app has been reloaded due to webrtc error\n * @property {string} UI_WATCHDOG - Indicates that ui app has been reloaded due to ui watchdog not receiving ui frames\n */\nexport const ConnectReason = Object.freeze({\n UNKNOWN: \"unknown\",\n INITIAL_CONNECTION: \"initial_connection\",\n UI_RELEASE: \"ui_release\",\n UI_TERMINATION: \"ui_termination\",\n WEBRTC_ERROR: \"webrtc_error\",\n UI_WATCHDOG: \"ui_watchdog\"\n});\n\nlet connectReason = ConnectReason.UNKNOWN;\nlet triggerEvent = {};\n\nimport {remotePlayer} from \"./remotePlayer\";\nexport {remotePlayer};\n\n/** Should be called once to init the library\n *@example\n * import { init } from \"senza-sdk\";\n * await init();\n **/\nexport async function init() {\n sdkLogger.log(`init ${version}`);\n\n if (!window.diagnostics) {\n sdkLogger.error(\"[ init ] window.diagnostics is undefined\");\n }\n\n if (window.cefQuery) {\n\n // First, check compatability with ui-streamer api version\n await new Promise((resolve, reject) => {\n window.cefQuery({\n request: \"apiVersion \" + API_VERSION,\n persistent: false,\n onSuccess: () => {\n sdkLogger.log(\"api version compatability check succeeded\");\n resolve();\n },\n onFailure: (code, msg) => {\n sdkLogger.error(\"api version compatability check failed: \" + msg);\n reject(msg);\n }\n });\n });\n\n const sessionInfoStr = await new Promise((resolve) => {\n window.cefQuery({\n request: \"sessionInfo\",\n persistent: false,\n onSuccess: (response) => {\n sdkLogger.log(\"sessionInfo request successfully returned \" + response);\n resolve(response);\n },\n onFailure: (code, msg) => {\n sdkLogger.error(`sessionInfo request failed: ${code} ${msg}`);\n }\n });\n });\n\n sessionInfo.setSessionInfoStr(sessionInfoStr);\n const sessionInfoObj = JSON.parse(sessionInfoStr);\n authToken = sessionInfoObj?.settings?.webUI?.backendHeaders?.Authorization;\n sdkLogger.log(`authToken: token = ${authToken}`);\n // Listen to updateSession event to set the new token\n document.addEventListener(\"updateSession\", (e) => {\n authToken = e.detail?.updateObj;\n sdkLogger.log(`onUpdateSessionEvent: token = ${authToken}`);\n });\n\n if (sessionInfoObj?.settings?.[\"ui-streamer\"]?.enableKeyPressDuration) {\n enableKeyPressIndicator();\n }\n\n // Get connection reason\n connectReason = await new Promise((resolve) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = { type: \"connectReason\", fcid: FCID };\n const request = { target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: (response) => {\n logger.log(`connectReason request successfully returned '${response}'`);\n resolve(response);\n },\n onFailure: (code, msg) => {\n logger.error(`connectReason request failed: ${code} ${msg}`);\n resolve(ConnectReason.UNKNOWN);\n }\n });\n });\n\n // Get trigger event\n // Currently the known types (and details per type) are:\n // keyPressEvent (keyValue)\n // alarmFiredEvent (alarmName, payload)\n // userAlertEvent (eventCode, message)\n // externalEvent (eventName, payload)\n // videoPlaybackEvent (eventCode, errorCode)\n const triggerEventStr = await new Promise((resolve) => {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n const message = { type: \"triggerEvent\", fcid: FCID };\n const request = { target: \"UI-Streamer\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: (response) => {\n logger.log(`triggerEvent request successfully returned '${response}'`);\n resolve(response);\n },\n onFailure: (code, msg) => {\n logger.error(`triggerEvent request failed: ${code} ${msg}`);\n resolve(\"\");\n }\n });\n });\n triggerEvent = {};\n let originalTriggerEvent = {};\n if (triggerEventStr) {\n try {\n originalTriggerEvent = JSON.parse(triggerEventStr);\n triggerEvent.type = originalTriggerEvent.type;\n if (triggerEvent.type === \"keyPressEvent\") {\n triggerEvent.data = { keyValue: originalTriggerEvent.keyValue };\n } else if (triggerEvent.type === \"alarmFiredEvent\") {\n triggerEvent.data = { alarmName: originalTriggerEvent.alarmName, payload: originalTriggerEvent.payload };\n } else if (triggerEvent.type === \"userAlertEvent\") {\n triggerEvent.data = { eventCode: originalTriggerEvent.eventCode, message: originalTriggerEvent.message };\n } else if (triggerEvent.type === \"externalEvent\") {\n triggerEvent.data = { eventName: originalTriggerEvent.eventName, payload: originalTriggerEvent.payload };\n } else if (triggerEvent.type === \"videoPlaybackEvent\") {\n triggerEvent.data = { eventCode: originalTriggerEvent.eventCode, errorCode: originalTriggerEvent.errorCode };\n } else {\n sdkLogger.warn(\"unknown trigger event type\", triggerEvent.type);\n }\n } catch (e) {\n sdkLogger.error(`failed to parse trigger event string ${triggerEventStr}: ${e.message}`);\n }\n }\n\n await remotePlayer._init(sessionInfoObj?.settings?.[\"ui-streamer\"], originalTriggerEvent);\n\n } else {\n authToken = getPlatformInfo().sessionInfo?.settings?.webUI?.backendHeaders?.Authorization;\n sdkLogger.log(`authToken dummy: token = ${authToken}`);\n }\n\n // Adding auth to window for testing purpose which allows us to use and test auth APIs in pipeline tests\n window.auth = auth;\n\n // override window.close() since it's not allowed to close the application this way\n window.close = () => {\n sdkLogger.warn(\"window.close is disabled on Senza platform. Use lifecycle.exitApplication() instead.\");\n };\n}\n\n/** Returns the reason the ui has been loaded\n * @returns {ConnectReason} */\nexport function getConnectReason() {\n return connectReason;\n}\n\n/** Returns the event that triggered the reloading of the ui after ui has been released\n * @returns {Object} trigger event\n * @property {string} type - the type of the trigger event (e.g. keyPressEvent, videoPlaybackEvent)\n * @property {object} data - data of the event, dependent on its type (e.g. keyPressEvent has data of keyValue) */\nexport function getTriggerEvent() {\n return triggerEvent;\n}\n\n// Returns the platform information, including version, pod, pod ip and session info.\nexport function getPlatformInfo() {\n if (typeof window !== \"undefined\" && window.diagnostics) {\n try {\n const platformInfo = window.diagnostics() || {};\n platformInfo.sessionInfo = sessionInfo.sessionInfoObj;\n return platformInfo;\n } catch (e) {\n sdkLogger.error(\"Could not get platform info\", e.stack);\n }\n\n } else {\n if (typeof window !== \"undefined\" && !window.diagnostics) {\n sdkLogger.error(\"[ getPlatformInfo ] window.diagnostics is undefined\");\n }\n return {\n version: \"X.X.XX-X\",\n pod: \"ui-streamer-X.X.XX-X-QWERT-ASDFG-XXX-XXXXXX-XXXXX\",\n podIP: \"0.0.0.0\",\n sessionInfo: {\n userAgent: \"SynamediaSenza/XX.YY.ZZ\",\n connectionId: \"dummy\",\n deviceId: \"123456789\",\n community: \"LocalDev\",\n tenant: \"XXXXXX\",\n tenantId: \"XXXXXX\",\n manifest: {\n transcontainer: \"X.X.XX-X\"\n },\n settings: {\n webUI: {\n backendHeaders: {\n Authorization: \"Bearer dummytoken\"\n }\n }\n },\n homeSessionInfo: {\n tenantId: \"XXXXXX\",\n community: \"LocalDev\"\n }\n }\n };\n }\n}\n\n/**\n *\n * @param {string} timezone the timezone to set to\n * the format of the timezone is according to the standard TZ identifier\n * (e.g. America/Los_Angeles, Asia/Tokyo, Europe/Brussels)\n * for a full list of TZ identifiers, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n */\nexport function setTimezone(timezone) {\n if (window.cefQuery) {\n const request = {message: JSON.stringify({type: \"setTimeZone\", timezone}), waitForResponse: false, target: \"UI-Streamer\"};\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n sdkLogger.log(\"timezome is successfully set to\", timezone);\n },\n onFailure: (code, msg) => {\n sdkLogger.error(`error occurred setting timezone to ${timezone}: ${code} ${msg}`);\n }\n });\n }\n}\n\nasync function getToken() {\n if (!authToken) {\n sdkLogger.log(\"getToken wait for promise updateSession event\");\n return new Promise((resolve) => {\n // Listen to updateSession event to set the new token\n document.addEventListener(\"updateSession\", (e) => {\n authToken = e.detail?.updateObj;\n sdkLogger.log(`onUpdateSessionEvent: token= ${authToken}`);\n resolve(authToken);\n }, {once:true});\n });\n }\n return Promise.resolve(authToken);\n}\n\nfunction forceTokenUpdate() {\n authToken = null;\n\n if (window.cefQuery) {\n const FCID = getFCID();\n const logger = sdkLogger.withFields({FCID});\n logger.log(\"forceTokenUpdate: sending updateSessionRequest\");\n const message = {\n type: \"updateSessionRequest\",\n updateKey: \"authorization\",\n parentPath: \"settings.webUI.backendHeaders.Authorization\",\n fcid: FCID\n };\n const request = { target:\"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n logger.log(\"updateSessionRequest successfully sent\");\n },\n onFailure: (code, msg) => {\n logger.error(`updateSessionRequest failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.error(\"forceTokenUpdate: window.cefQuery is undefined\");\n }\n}\n\n/** Returns a boolean that indicates whether we are running in an e2e environment, or on local browser */\nexport function isRunningE2E() {\n return !!(typeof window !== \"undefined\" && window.cefQuery);\n}\n\n/** Call this API once after application startup, when the ui is ready to accept keys/events */\nexport function uiReady() {\n if (window.cefQuery) {\n window.cefQuery({\n request: \"uiReady\",\n persistent: false,\n onSuccess: () => {\n sdkLogger.log(\"uiReady request successfully sent\");\n },\n onFailure: (code, msg) => {\n sdkLogger.error(`uiReady request failed: ${code} ${msg}`);\n }\n });\n } else {\n sdkLogger.error(\"uiReady: window.cefQuery is undefined\");\n }\n}\n\n/**\n * @deprecated use deviceManager.deviceInfo instead.\n * Returns the device information, including device id, connection id, community, tenant and client ip\n * */\nexport function getDeviceInfo() {\n // STOP DO NOT CHANGE THIS FUNCTION AS IT IS DEPRECATED!!!!\n const sessionInfoObj = sessionInfo.sessionInfoObj;\n if (isRunningE2E()) {\n return {\n deviceId: sessionInfoObj.deviceId,\n connectionId: sessionInfoObj.connectionId,\n community: sessionInfoObj.community,\n tenant: sessionInfoObj.tenant,\n clientIp: sessionInfoObj.clientIp\n };\n }\n sdkLogger.log(\"getDeviceInfo running locally, returning dummy info\");\n return {\n deviceId: \"123456789\",\n connectionId: \"dummy\",\n community: \"LocalDev\",\n tenant: \"XXXXXX\",\n clientIp: \"0.0.0.0\"\n };\n}\n\n\nexport {lifecycle} from \"./lifecycle\";\nexport {deviceManager} from \"./deviceManager\";\nexport {alarmManager} from \"./alarmManager\";\nexport {messageManager} from \"./messageManager\";\nimport \"./devHelper\";\n\n/**\n * @example\n * import { envInfo } from \"senza-sdk\";\n * console.info(envInfo.remoteBrowserIp)\n *\n * @version 3.1.1\n * @property {string} envInfo.remoteBrowserIp - the ip of the remote browser, can be used for remote debugging\n * @property {string} envInfo.sdkVersion - the version of the SDK\n */\nexport const envInfo = {\n remoteBrowserIp: window.diagnostics ? window.diagnostics().podIP : \"127.0.0.1\",\n sdkVersion: version\n};\n\n/**\n * The function receives a license response and passes it to platform.\n * @param {number} statusCode status code that was received from the license server\n * @param {ArrayBuffer|string} licenseResponse a license response that was received from the license server to be passed to platform.\n * @param {string} fcid a fcid received with the license request\n * @param {string} sessionId a sessionId received with the license request\n * In case of success licenceResponse is of type @type {ArrayBuffer}\n * In case of error licenseResponse is of type @type {string}\n */\nexport function writeLicenseResponse(statusCode, licenseResponse, fcid, sessionId) {\n\n if (statusCode === 200) {\n licenseResponse = window.btoa(String.fromCharCode.apply(null, new Uint8Array(licenseResponse))); // to base64\n }\n\n if (window.cefQuery) {\n const message = {\n type: \"updateLicense\",\n sessionId,\n fcid\n };\n message[statusCode === 200 ? \"response\" : \"error\"] = licenseResponse;\n const request = { target: \"TC\", waitForResponse: false, message: JSON.stringify(message) };\n window.cefQuery({\n request: JSON.stringify(request),\n persistent: false,\n onSuccess: () => {\n sdkLogger.log(\"updateLicense request successfully sent\");\n },\n onFailure: (code, msg) => {\n sdkLogger.error(`updateLicense request failed: ${code} ${msg}`);\n }\n });\n }\n\n}\n\nexport class ClientAssertionError extends Error {\n constructor(code,message) {\n super(message);\n this.code = code;\n }\n}\n\n/**\n * @typedef Token\n * @property {string} hostplatform_assertion The client assertion token.\n*/\n\n/**\n * Async function that returns the client assertion\n * @return {Promise<Token>} Promise which is resolved to a client assertion object when getClientAssertion has been successfully performed. * client assertion object contains hostplatform_assertion property which holds the client assertion token.\n * Failure to getClientAssertion for any reason, result in the promise being rejected.\n * Error status codes:\n * Status code 400 - Tenant configuration is missing\n * Status code 0 - General error\n * @example\n * try {\n * const client_assertion = await auth.getClientAssertion();\n * console.log(\"Client assertion token is\", client_assertion.hostplatform_assertion);\n * } catch (e) {\n * console.error(\"getClientAssertion failed\", e);\n * }\n */\nexport function getClientAssertion() {\n if (window.cefQuery) {\n sdkLogger.log(\"getClientAssertion is called\");\n\n return new Promise((resolve, reject) => {\n window.cefQuery ({\n request: \"client_assertion\",\n persistent: false,\n onSuccess: (response) => {\n try {\n const json_response = JSON.parse(response);\n sdkLogger.log(`client_assertion request successfully returned ${response}`);\n resolve(json_response);\n } catch (e) {\n sdkLogger.error(`Failed to parse client assertion ${response}`);\n reject(new ClientAssertionError(0, \"Failed to parse client assertion\"));\n }\n\n },\n onFailure: (code, msg) => {\n sdkLogger.log(`client_assertion request failed: ${code} ${msg}`);\n reject(new ClientAssertionError(code, msg));\n }\n });\n });\n }\n sdkLogger.warn(\"getClientAssertion is not supported if NOT running e2e\");\n}\n\n// Assign the senza library to the old name (hs) for backward compatibility\nimport * as senzaSDK from \"./api.js\";\nif (typeof window !== \"undefined\") {\n window.hs = senzaSDK;\n}\n","export function enableKeyPressIndicator() {\n const keyPressIndicator = document.createElement(\"div\");\n keyPressIndicator.setAttribute(\"style\", \"height: 8px; width: 8px; background-color: red; position: absolute; left: 0px; top: 0px; z-index: 9999;\");\n document.body.appendChild(keyPressIndicator);\n document.addEventListener(\"keydown\", () => {\n if (keyPressIndicator.style.backgroundColor === \"red\") {\n keyPressIndicator.style.backgroundColor = \"blue\";\n } else if (keyPressIndicator.style.backgroundColor === \"blue\") {\n keyPressIndicator.style.backgroundColor = \"green\";\n } else { // background color is green\n keyPressIndicator.style.backgroundColor = \"red\";\n }\n });\n}\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","version","getFCID","Math","round","random","getPlatformInfo","sessionInfo","connectionId","SdkLogger","constructor","logFields","debug","data","console","formatLogString","log","info","warn","error","withFields","logString","join","JSON","stringify","sdkLogger","sdkVersion","url","window","location","href","sessionInfoStr","sessionInfoObj","parse","e","setSessionInfoStr","objStr","Error","Lifecycle","EventTarget","super","document","addEventListener","detail","event","Event","state","dispatchEvent","getState","cefQuery","Promise","resolve","reject","request","persistent","onSuccess","response","onFailure","code","msg","moveToForeground","FCID","logger","action","fcid","moveToBackground","switchTenant","tenantId","length","contentHubTenantId","homeSessionInfo","tenantInfo","homeTenantId","message","type","session","btoa","returnToTenantId","target","waitForResponse","exitApplication","splashUrl","tenantSettings","applicationSwitchSplashUrl","contentHubTenantInfo","lifecycle","cloneDeep","element","RemotePlayerError","getPlaybackInfo","playbackInfoStr","playbackPosition","assetDuration","playbackInfo","RemotePlayer","_config","preferredAudioLanguage","preferredSubtitlesLanguage","_selectedAudioTrack","_selectedSubtitlesTrack","_availableAudioTracks","_availableTextTracks","_textTrackVisibility","_ptsSessionId","_videoElement","undefined","_isInitialized","_availabilityStartTime","availabilityStartTime","_updateTracks","playbackRate","rate","eventCode","CustomEvent","getLicenseEventData","buffer","Uint8Array","from","c","charCodeAt","licenseRequest","ArrayBuffer","byteLength","set","sessionId","licenseRequestEvent","writeLicenseResponse","statusCode","responseBody","LoadMode","freeze","NOT_LOADED","LOADING","LOADED","_init","uiStreamerSettings","triggerEvent","playerState","isLoaded","playbackUrl","playerStateStr","_loadMode","_loadedUrl","_setPlayableUriTimeout","setPlayableUriTimeout","_requestVideoFrameInfo","requestVideoFrameInfo","playbackMetadata","availableAudioTracks","availableSubtitlesTracks","assetType","sourceLanguagesList","sort","a","b","lang","toLowerCase","translationLangs","id","mergedList","tl","find","autoTranslate","push","mergeAutoTranslationLanguages","selectedTrack","track","selected","getConfiguration","configure","props","entries","forEach","_changeLoadMode","newLoadMode","_handle_video_frame_info","videoElement","videoFrameCallback","now","metadata","currentFramePTS","mediaTime","toString","ptsSessionId","requestVideoFrameCallback","_reset","registerVideoElement","video","load","position","previousLoadMode","currentTime","loadUrl","timeout","autoPlay","timerId","timeBeforeSendingRequest","Date","queryId","duration","clearTimeout","loadTimeout","setTimeout","cefQueryCancel","unload","play","audioLanguage","subtitlesLanguage","class","pause","getAssetUri","getLoadMode","getTextTracks","getAudioTracks","selectAudioTrack","audioTrackId","selectTextTrack","textTrackId","setTextTrackVisibility","visible","oldVisibility","TypeError","newVisibility","setPlaybackInfo","textTrackVisibility","getPresentationStartTimeAsDate","remotePlayer","wifiInfo","DeviceManager","level","quality","ssid","bssid","deviceInfo","isRunningE2E","deviceId","community","tenant","clientIp","countryCode","general","reboot","clearWifi","sendDataToDevice","command","payload","factoryReset","timeoutHandler","FACTORY_RESET_TIMEOUT_SECONDS","deviceManager","AlarmManager","alarmName","addAlarm","alarmTime","deleteAlarm","deleteAllAlarms","getActiveAlarms","alarmManager","MessageManager","eventName","registerGroups","groups","messageManager","currentState","then","handleHintLogging","authToken","API_VERSION","auth","getToken","async","updateObj","once","forceTokenUpdate","updateKey","parentPath","getClientAssertion","ConnectReason","UNKNOWN","INITIAL_CONNECTION","UI_RELEASE","UI_TERMINATION","WEBRTC_ERROR","UI_WATCHDOG","connectReason","init","diagnostics","settings","webUI","backendHeaders","Authorization","enableKeyPressDuration","keyPressIndicator","createElement","setAttribute","body","appendChild","style","backgroundColor","enableKeyPressIndicator","triggerEventStr","originalTriggerEvent","keyValue","errorCode","close","getConnectReason","getTriggerEvent","pod","podIP","userAgent","manifest","transcontainer","platformInfo","stack","setTimezone","timezone","uiReady","getDeviceInfo","envInfo","remoteBrowserIp","licenseResponse","String","fromCharCode","apply","ClientAssertionError","json_response","hs"],"sourceRoot":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "senza-sdk",
|
|
3
|
+
"version": "0.0.356",
|
|
4
|
+
"main": "./dist/bundle.js",
|
|
5
|
+
"types": "src/api.d.ts",
|
|
6
|
+
"description": "API for Senza application",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://senza.synamedia.com",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"clean": "rm -rf dist",
|
|
14
|
+
"prepublish": "npm run build",
|
|
15
|
+
"eslint": "eslint --max-warnings 0 src test",
|
|
16
|
+
"build": "npx webpack --config webpack.config.js",
|
|
17
|
+
"test": "jest --coverage"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@babel/cli": "^7.13.16",
|
|
21
|
+
"@babel/core": "7.18.6",
|
|
22
|
+
"@babel/plugin-transform-modules-commonjs": "^7.16.8",
|
|
23
|
+
"@babel/preset-env": "^7.14.1",
|
|
24
|
+
"babel-jest": "^27.5.1",
|
|
25
|
+
"eslint": "^8.40.0",
|
|
26
|
+
"eslint-plugin-jest": "^26.1.1",
|
|
27
|
+
"jest": "^27.5.1",
|
|
28
|
+
"jsdoc-to-markdown": "^7.1.1",
|
|
29
|
+
"ts-loader": "^9.5.1",
|
|
30
|
+
"webpack": "^5.72.1",
|
|
31
|
+
"webpack-cli": "^5.1.4"
|
|
32
|
+
},
|
|
33
|
+
"jest": {
|
|
34
|
+
"verbose": false,
|
|
35
|
+
"testEnvironment": "jsdom",
|
|
36
|
+
"moduleDirectories": [
|
|
37
|
+
"src",
|
|
38
|
+
"node_modules"
|
|
39
|
+
],
|
|
40
|
+
"coverageThreshold": {
|
|
41
|
+
"global": {
|
|
42
|
+
"branches": 84,
|
|
43
|
+
"functions": 89,
|
|
44
|
+
"lines": 91,
|
|
45
|
+
"statements": 91
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|