UNPKG

hbbtv-lib

Version:

Library for common functionality needed in HbbTV applications.

983 lines (845 loc) 31.1 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["sync_manager"] = factory(); else root["hbbtvLib"] = root["hbbtvLib"] || {}, root["hbbtvLib"]["src"] = root["hbbtvLib"]["src"] || {}, root["hbbtvLib"]["src"]["cs"] = root["hbbtvLib"]["src"]["cs"] || {}, root["hbbtvLib"]["src"]["cs"]["sync_manager"] = factory(); })(typeof self !== 'undefined' ? self : this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { /* * Copyright: IRT 2019 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var Emitter = __webpack_require__(1).EventEmitter; var inherit = __webpack_require__(2); /** * @external EventEmitter * @see https://nodejs.org/api/events.html */ /** * The CII endpoint of the HbbTV terminal has been disabled. * @event SyncManager#EVT_CII_DISABLED */ /** * The CII endpoint of the HbbTV terminal has been enabled. * @event SyncManager#EVT_CII_ENABLED */ /** * An error occured * @event SyncManager#EVT_ERROR * @param {string} message A textual description of what happened */ /** * An error occured * @event SyncManager#EVT_MS_ERROR * @param {string} message A textual description of what happened */ /** * @exports SyncManager * @class SyncManager * * @classdesc * Simplifies the use of the Media Synchroniser Object API of HbbTV 2.0 * * <p>SyncManager may fire the following events: * <ul> * <li>[EVT_CII_DISABLED]{@link SyncManager#event:EVT_CII_DISABLED}</li> * <li>[EVT_CII_ENABLED]{@link SyncManager#event:EVT_CII_ENABLED}</li> * <li>[EVT_ERROR]{@link SyncManager#event:EVT_ERROR}</li> * <li>[EVT_MS_ERROR]{@link SyncManager#event:EVT_MS_ERROR}</li> * </ul> * * @example <caption>Enable inter-device synchronisation with video/broadcast</caption> * var SyncManager = require('hbbtv-lib/cs/sync_manager'); * * mediaObj = document.getElementById("vbObject"); * mediaObj.bindToCurrentChannel(); * * // wait for presenting state * syncMan = new SyncManager(); * * syncMan.on(SyncManager.EVT_MS_ERROR, on_ms_error); * syncMan.once(SyncManager.EVT_CII_ENABLED, on_cii_enabled); * syncMan.once(SyncManager.EVT_CII_DISABLED, on_cii_disabled); * * syncMan.setMasterMedia(mediaObj, "urn:dvb:css:timeline:temi:1:1"); * syncMan.enableCII(); * * function on_cii_enabled() { * log("synchronisation with companion can be started."); * } * * @constructor * * @augments external:EventEmitter */ function SyncManager() { try { this.syncMan = oipfObjectFactory.createMediaSynchroniser(); } catch (e) { throw new Error("Can't instantiate Media Synchroniser"); } if (!this.syncMan || typeof this.syncMan.initMediaSynchroniser != "function") { this.syncMan = null; throw new Error("No MediaSynchroniser available"); } var that = this; this.syncMan.onerror = this.syncMan.onError = function (/*Number*/lastError, /*Object*/lastErrorSource) { var errorDescription = "unknown"; var isTransient = false; switch (lastError) { case 1: errorDescription = "Synchronization is unachievable because the terminal could not delay presentation of " + "content (represented by a media object added using the addMediaObject() method) " + "sufficiently to synchronize it with the master media. For example: the buffer size for " + "media synchronization is not sufficient."; isTransient = true; break; case 2: errorDescription = "The presentation of media object(that was added using the addMediaObject() method) " + "failed. The specific reason is given by the error handler of that media object. "; isTransient = true; break; case 3: errorDescription = "The media or the selected timeline for the media could not be found or the media " + "timeline is no longer present (for media represented by a media object that was added " + "using the addMediaObject() method). "; isTransient = true; break; case 4: errorDescription = " Media object is already associated with the MediaSynchroniser."; isTransient = true; break; case 5: errorDescription = "The correlation timestamp set for a media object is null or has an invalid format."; isTransient = true; break; case 6: errorDescription = "Inter-device synchronization with a master terminal failed because of unavailability, e.g. " + "an endpoint is not available or disappeared. Applications should rediscover available " + "terminals as defined in clause 14.7.2 before continuing with inter-device synchronization. "; break; case 7: errorDescription = " The call failed because the MediaSynchroniser is not yet initialized."; isTransient = true; break; case 8: errorDescription = "The media object referenced as an argument in the call needed to have already been " + "added to the MediaSynchroniser using the addMediaObject() method, but it has not " + "been. "; isTransient = true; break; case 9: errorDescription = "The media object (that was passed using the addMediaObject() method) is not in a " + "suitable state to participate in synchronization. See clause 9.7.1. "; isTransient = true; break; case 10: errorDescription = "Inter-device synchronization with a master terminal failed because of a fault in protocol " + "interaction, e.g. the master terminal did not provide required messages or data. " + "Applications can consider trying again. "; break; case 11: errorDescription = "Synchronization is unachievable because the terminal could not present the content " + "(represented by a media object added using the addMediaObject() method) " + "sufficiently early to synchronize it with the master media. "; isTransient = true; break; case 13: errorDescription = "The method call failed because the MediaSynchroniser is in a permanent error state or " + "because it has been replaced by a newer initialized MediaSynchroniser. "; isTransient = true; break; case 14: errorDescription = "The presentation of the master media (that was specified as an argument when the " + "initMediaSynchroniser() method was called) failed. The specific reason is given by " + "the error handler of that media object. "; break; case 15: errorDescription = "The master media object or the selected timeline for a media object could not be found " + "or the media timeline is no longer present. "; break; case 16: errorDescription = " The master media object is not in a suitable state to participate in synchronization. See " + "clause 9.7.1. "; break; case 17: errorDescription = " The method call failed because the MediaSynchroniser is already initialized."; isTransient = true; break; case 18: errorDescription = "The MediaSynchroniser has been replaced by a new MediaSynchroniser being " + "initialized. "; break; case 19: errorDescription = "The master terminal has reported that the presentationStatus of the master media has " + "changed to 'transitioning' (see clause 13.6.3). "; isTransient = true; break; } that.log (errorDescription); that.emit(SyncManager.EVT_MS_ERROR, lastError, isTransient, errorDescription); } // this.syncMan.onSyncNowAchievable = function (o) { // } } inherit(SyncManager, Emitter); /** * Adds the master media to the sync manager, i.e. by calling initMediaSynchroniser. Note: this can be called only once. * * @param {media_object} master - either a A/V or V/B object, or an HTML5 media element in a suitable state for media synchronisation. * @param {string} tl_spec - a synchronisation timeline specifier. * * @returns {boolean} TRUE if method executed without errors, else FALSE. * * @fires SyncManager#EVT_ERROR */ SyncManager.prototype.setMasterMedia = function (master, tl_spec) { if (this.syncMan == null) { this.emit(SyncManager.EVT_ERROR, "Internal HbbTV MediaSynchroniser object is null."); return false; } if (this.masterMedia) { this.emit(SyncManager.EVT_ERROR, "The media synchroniser already has a master element."); return false; } if (!master) { this.emit(SyncManager.EVT_ERROR, "Need to call with a supported HbbTV media element."); return false; } if (!checkMediaState(master)) { this.emit(SyncManager.EVT_ERROR, "The media element is not in a sufficient state to get a master in HbbTV media synchronisation."); return false; } if (tl_spec && !checkTLSpec(tl_spec)) { this.emit(SyncManager.EVT_ERROR, "The timeline spec is not valid: "+ tl_spec); return false; } else if (!tl_spec && !(tl_spec = inferTLSpecFromMedia(master)) ) { this.emit(SyncManager.EVT_ERROR, "Can't infer timeline spec from given media element."); return false; } this.masterMedia = master; this.syncMan.initMediaSynchroniser(master, tl_spec); this.log("initMediaSync: " + tl_spec); return true; } /** * Adds the media object to the sync manager, i.e. by calling addMediaObject. * * @param {object} mediaObject - either a A/V or V/B object, or an HTML5 media element in a suitable state for media synchronisation. * @param {string} tl_spec - a synchronisation timeline specifier. * @param {object} cor - an object providing a correlation tuple (support dvbcss_clocks from BBC and MRS formats) * * @returns {boolean} TRUE if method executed without errors, else FALSE. * * @fires SyncManager#EVT_ERROR */ SyncManager.prototype.addMediaObject = function (obj, tl_spec, cor) { if (this.syncMan == null) { this.emit(SyncManager.EVT_ERROR, "Internal HbbTV MediaSynchroniser object is null."); return false; } if (!this.masterMedia) { this.emit(SyncManager.EVT_ERROR, "The media synchroniser is not initialised with a master element."); return false; } if (!obj) { this.emit(SyncManager.EVT_ERROR, "Need to call with a supported HbbTV media element."); return false; } if (!checkMediaState(obj)) { this.emit(SyncManager.EVT_ERROR, "The media element is not in a sufficient state to participate in HbbTV media synchronisation."); return false; } if (tl_spec && !checkTLSpec(tl_spec)) { this.emit(SyncManager.EVT_ERROR, "The timeline spec is not valid: "+ tl_spec); return false; } else if (!tl_spec && !(tl_spec = inferTLSpecFromMedia(obj)) ) { this.emit(SyncManager.EVT_ERROR, "Can't infer timeline spec from given media element."); return false; } cor = translate_correlation_ts(cor); this.log("Add media object with " + tl_spec + " : cor " + cor); this.syncMan.addMediaObject(obj, tl_spec, cor); return true; } /** * Removes the media object from the sync manager, i.e. by calling removeMediaObject. * * @param {video|audio|object} obj - either a A/V or V/B object, or an HTML5 media element in a suitable state for media synchronisation. * * @returns {boolean} TRUE if method executed without errors, else FALSE. * * @fires SyncManager#EVT_ERROR */ SyncManager.prototype.addMediaObject = function (obj) { if (this.syncMan == null) { this.emit(SyncManager.EVT_ERROR, "Internal HbbTV MediaSynchroniser object is null."); return false; } if (!obj) { this.emit(SyncManager.EVT_ERROR, "Need to call with a supported HbbTV media element."); return false; } this.syncMan.removeMediaObject(obj); return true; } /** * Checks whether a timeline specifier is syntactically correct. Supports CT, DASH, PTS and TEMI. * * @param {string} tls the DVB CSS timeline specifier. * @returns {boolean} Returns TRUE if correct, else FALSE. * @private */ function checkTLSpec (tls) { // https://regex101.com/r/MVX8is/2/ var regex = /^urn:dvb:css:timeline:(mpd:period:rel:[0-9]+(:[a-z0-9]+)?|pts|ct|temi:[0-9]+:[0-9]+)$/gm; return regex.test(tls); } /** * Retrieves timeline specifier from mime type or URL of the media element. * @param {object} media element * @returns {string|boolean} Timeline specifier or FALSE if timeline specifier could not be retrieved. * @private */ function inferTLSpecFromMedia(o) { if (!o) return false; if (o.tagName.toLowerCase() == "object") { switch (o.getAttribute("type")) { case "video/broadcast": return "urn:dvb:css:timeline:pts"; // if apps require TEMI need to specify themselve. case "video/mp4": case "audio/mp4": return "urn:dvb:css:timeline:ct"; case "application/dash+xml": return "urn:dvb:css:timeline:mpd:period:rel:1000"; // if apps require specific period or tickrate need to specify this themselve } } else if (o.tagName.toLowerCase() == "video" || o.tagName.toLowerCase() == "audio") { if (o.currentSrc.indexOf(".mp4")>0) { return "urn:dvb:css:timeline:ct"; } else if (o.currentSrc.indexOf(".mpd")>0) { return "urn:dvb:css:timeline:mpd:period:rel:1000"; } } return false; } /** * Checks whether an object is in a state to be added to the MediaSynchroniser. * * @see HbbTV2.0 chapter 9.7.1 * * @param {HTMLElement} o * * @returns {boolean} TRUE if object can be added to the MediaSynchroniser, else FALSE. * @private */ function checkMediaState (o) { if (!o instanceof HTMLElement) return false; if (o.tagName.toLowerCase() == "object") { if (o.getAttribute("type") == "video/broadcast") { return (o.playState == 2 || o.playState == 1); } else { return (o.playState >= 1 && o.playState <= 4); } } else if (o.tagName.toLowerCase() == "video" || o.tagName.toLowerCase() == "audio") { return (o.readyState >= o.HAVE_CURRENT_DATA) ; } return false; } /** * Enables inter-device synchronisation for MediaSynchroniser that is properly initialized. * An event is fired when the service endpoints (e.g. DVB CII) are operational. * * @returns {boolean} true if the SyncManager is initialized properly. * * @fires SyncManager#EVT_CII_ENABLED */ SyncManager.prototype.enableCII = function () { if (this.syncMan == null) return false; var that = this; this.syncMan.enableInterDeviceSync( function () { that.log("enableCII: inter-device sync enabled."); that.emit (SyncManager.EVT_CII_ENABLED); } ); this.log("enableCII called enableInterDeviceSync."); return true; } /** * Disables inter-device synchronisation. Closes the terminals CII endpoints. * @returns {boolean} * * @fires SyncManager#EVT_CII_DISABLED */ SyncManager.prototype.disableCII = function () { if (this.syncMan == null) return false; var that = this; this.syncMan.disableInterDeviceSync(function (){ that.emit(SyncManager.EVT_CII_DISABLED); }); } /** * Returns current position on the media timeline * @returns {number} Current time */ SyncManager.prototype.currentTime = function () { if (this.syncMan) { return this.syncMan.currentTime; } return null; } /** * Stops any active MediaSynchroniser, i.e. disables inter-device sync (aka DVB CSS). */ SyncManager.prototype.stop = function () { try { this.removeAllListeners(); this.removeAudioTrack(true); this.syncMan.removeMediaObject(this.masterMedia); this.masterMedia = null; this.syncMan = null; } catch (e) { this.log("stop(): " + e); } } /** * Creates an object that type is CorrelationTimestamp, as there was an ambigouity in the specification, * whether the timestamp required to have the type or not. * * @param {*} m a timestamp on the timeline of the master media. * @param {*} o a correlating timestamp on the timeline of the slave/other media used for multistream synchronisation. * @private */ function CorrelationTimestamp (m,o) { this.tlvMaster = m; this.tlvOther = o; } CorrelationTimestamp.prototype.toString = function () { return "tlvMaster = " + this.tlvMaster + "; tlvOther = " + this.tlvOther; } function translate_correlation_ts (cor) { var ts = new CorrelationTimestamp(0, 0); if (cor) { if (cor.point && cor.materialPoint) { ts.tlvMaster = parseInt (cor.point); ts.tlvOther = parseInt (cor.materialPoint); } else if (cor.parentTime && cor.childTime) { ts.tlvMaster = parseInt (cor.parentTime); ts.tlvOther = parseInt (cor.childTime); } } return ts; } /** * Event name constant for the [EVT_CII_DISABLED]{@link SyncManager#event:EVT_CII_DISABLED} event. */ SyncManager.EVT_CII_DISABLED = 0; /** * Event name constant for the [EVT_CII_ENABLED]{@link SyncManager#event:EVT_CII_ENABLED} event. */ SyncManager.EVT_CII_ENABLED = 1; /** * Event name constant for the [EVT_ERROR]{@link SyncManager#event:EVT_ERROR} event. */ SyncManager.EVT_ERROR = 2; /** * Event name constant for the [EVT_MS_ERROR]{@link SyncManager#event:EVT_MS_ERROR} event. */ SyncManager.EVT_MS_ERROR = 3; module.exports = SyncManager; /***/ }), /* 1 */ /***/ (function(module, exports) { // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); this._maxListeners = n; return this; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); err.context = er; throw err; } } } handler = this._events[type]; if (isUndefined(handler)) return false; if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (isObject(this._events[type])) // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); if (typeof console.trace === 'function') { // not supported in IE 10 console.trace(); } } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError('listener must be a function'); var fired = false; function g() { this.removeListener(type, g); if (!fired) { fired = true; listener.apply(this, arguments); } } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (isObject(list)) { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } delete this._events[type]; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (isFunction(this._events[type])) ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type]; if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; }; EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); }; function isFunction(arg) { return typeof arg === 'function'; } function isNumber(arg) { return typeof arg === 'number'; } function isObject(arg) { return typeof arg === 'object' && arg !== null; } function isUndefined(arg) { return arg === void 0; } /***/ }), /* 2 */ /***/ (function(module, exports) { /* * Copyright: IRT 2019 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } /** * Copies prototype from B to A, i.e. A extends/inherits B. * * @param {*} A child "class" * @param {*} B parent "class" * * @ignore */ function inherit (A, B) { if (typeof (A.prototype) == "object" && typeof (B.prototype) == "object") { A.prototype = Object.create(B.prototype); } } module.exports = inherit; /***/ }) /******/ ]); });