From 36f58655e8d01e2a5219cdb211ffb01cb29c6067 Mon Sep 17 00:00:00 2001 From: Alan Michaelsen Date: Sun, 6 Feb 2022 20:50:49 -0500 Subject: [PATCH 1/4] json update Updated position of the start button and profile card as well as creating the route api/schedule for the schedule to display its game info from --- package-lock.json | 1730 ++++++++++++++++++++++++++++++++++++++++- package.json | 1 + private/schedule.json | 10 + public/api.js | 32 + server.js | 11 +- views/home.ejs | 262 +++---- 6 files changed, 1909 insertions(+), 137 deletions(-) create mode 100644 private/schedule.json create mode 100644 public/api.js diff --git a/package-lock.json b/package-lock.json index c07a8a7..b9457ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,1731 @@ { "name": "majorityrules", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "majorityrules", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "ejs": "^3.1.6", + "express": "^4.17.1", + "fs": "^0.0.1-security", + "nodemon": "^2.0.12" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dependencies": { + "string-width": "^3.0.0" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "dependencies": { + "jake": "^10.6.1" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dependencies": { + "ini": "1.3.7" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dependencies": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "node_modules/jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dependencies": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "dependencies": { + "mime-db": "1.49.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", + "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", + "hasInstallScript": true, + "dependencies": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.3", + "update-notifier": "^4.1.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "engines": { + "node": ">=4" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "dependencies": { + "debug": "^2.2.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dependencies": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + } + }, "dependencies": { "@sindresorhus/is": { "version": "0.14.0", @@ -474,6 +2197,11 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", diff --git a/package.json b/package.json index 83a27c9..78ba748 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "ejs": "^3.1.6", "express": "^4.17.1", + "fs": "^0.0.1-security", "nodemon": "^2.0.12" } } diff --git a/private/schedule.json b/private/schedule.json new file mode 100644 index 0000000..5fb9b40 --- /dev/null +++ b/private/schedule.json @@ -0,0 +1,10 @@ +{ + "isActive": false, + "startTime": "2018-01-01T00:00:00.000Z", + "nextGameText": "Next Game", + "prizeCents": 500, + "currency": "USD", + "display": { + "logo": "/assets/logo.svg" + } +} \ No newline at end of file diff --git a/public/api.js b/public/api.js new file mode 100644 index 0000000..cb30952 --- /dev/null +++ b/public/api.js @@ -0,0 +1,32 @@ +let nextGameText = document.getElementById('nextGameText'); +let gameStatus = document.getElementById('nextGameInfo'); + +//Use fetch to get the json data from /api/schedule +fetch('/api/schedule') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + console.log(data); + let schedule = data + nextGameText.innerHTML = schedule.nextGameText; + let startTime = new Date(schedule.startTime); + let startTimeString = startTime.toLocaleString('en-US', { + weekday: 'long', + hour: 'numeric', + minute: 'numeric', + hour12: true + }); + + var num = schedule.prizeCents + num /= 100; + num.toLocaleString("en-US", {style:"currency", currency:"USD"}); + + gameStatus.innerHTML = `${startTimeString} $${num}`; + + //Set the src of the image in the gameLogo class to schedule.display.logo + document.getElementById('gameLogo').src = schedule.display.logo; + }) + .catch(function(err) { + console.log('Error: ' + err); +}); \ No newline at end of file diff --git a/server.js b/server.js index c1836d8..a7652f3 100644 --- a/server.js +++ b/server.js @@ -1,14 +1,23 @@ const express = require('express') +const fs = require('fs') const app = express() // set the view engine to ejs app.set('view engine', 'ejs'); app.use(express.static('public')); +// set the view engine to ejs +app.set('json spaces', 2); + // index page app.get('/', function(req, res) { res.render('home'); - }); +}); + +// Api Routes +app.get('/api/schedule', function(req, res) { + res.sendFile(__dirname + '/private/schedule.json'); +}); app.listen(8080); console.log('Server is listening on port 8080'); \ No newline at end of file diff --git a/views/home.ejs b/views/home.ejs index f40611b..ebe70a3 100644 --- a/views/home.ejs +++ b/views/home.ejs @@ -1,139 +1,131 @@ - - - - - - - Hello World - - - - - - - - - - - - - - - - - - - - -
next game
-
7pm tmrw, $200 prize
-
-
invite for extra lives
- - + .nextgame { + color: white; + font-family: 'Roboto', sans-serif; + font-size: 10pt; + width: 100%; + position: absolute; + top: 25%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; + } + .logo { + width: 40%; + display: block; + margin: auto; + margin-top: 10%; + } + .center { + height: 100vh; + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + body { + animation-name: bg_animation; + animation-duration: 15s; + animation-timing-function: linear; + animation-delay: 0; + animation-iteration-count: infinite; + animation-direction: alternate; + animation-play-state: running; + } + .startbtn { + background-color: rgba(255, 255, 255, 0.3); + position: absolute; + width: 90%; + bottom: 0px; + left: 50%; + transform: translate(-50%, 0px); + margin-right: 20px; + border-radius: 50px; + margin-bottom: 20px; + color: white; + padding: 20px 0px 20px 0px; + text-align: center; + font-size: 15pt; + font-family: 'Roboto', sans-serif; + } + .profilecard { + left: 50%; + height: 45%; + bottom: 100px; + border-radius: 20px; + transform: translate(-50%, 0); + background: white; + width: 90%; + position: absolute; + } + @keyframes bg_animation { + 0% { + background-color: hsl(157, 52%, 58%); /* green */ + } + 20% { + background-color: hsl(182, 52%, 57%); /* light blue */ + } + 40% { + background-color: hsl(225, 46%, 60%); /* blue */ + } + 60% { + background-color: hsl(280, 45%, 58%); /* purple */ + } + 80% { + background-color: hsl(323, 40%, 54%); /* pink */ + } + 100% { + background-color: hsl(32, 52%, 54%); /* orange */ + } + } + + \ No newline at end of file From 97b5cbff9d4f4e179647020a948f8c0ff9b07c90 Mon Sep 17 00:00:00 2001 From: Alan Michaelsen Date: Tue, 22 Feb 2022 20:41:47 -0500 Subject: [PATCH 2/4] added socket and flv support Added support for WebSocket for sending questions and FLV for playing live FLV streams --- .DS_Store | Bin 0 -> 8196 bytes package-lock.json | 770 +- package.json | 4 +- private/config.json | 27 + private/leaderboard.json | 9 + private/me.json | 1 + private/schedule.json | 17 +- public/.DS_Store | Bin 0 -> 6148 bytes public/api.js | 32 - public/assets/.DS_Store | Bin 0 -> 8196 bytes public/assets/live-games/live-viewer.svg | 1 + public/assets/live-games/logo-dark.png | Bin 0 -> 1791 bytes public/assets/live-games/logo-norm.png | Bin 0 -> 1697 bytes .../assets/live-games/logo-sports-trans50.png | Bin 0 -> 6265 bytes public/assets/live-games/logo-sports.png | Bin 0 -> 4259 bytes .../majorityrules2-derivatives/.DS_Store | Bin 0 -> 6148 bytes public/css/debug.css | 50 + public/css/liveGame.css | 136 + public/css/schedule.css | 123 + public/js/.DS_Store | Bin 0 -> 6148 bytes public/{ => js}/app.js | 0 public/js/flv.js | 9980 +++++++++++++++++ public/js/liveGame.js | 63 + public/js/schedule/api.js | 104 + public/js/schedule/config.js | 39 + public/js/schedule/debug.js | 14 + public/js/schedule/player.js | 11 + public/{ => js}/serviceWorker.js | 0 server.js | 128 +- socket/showToast.json | 5 + socket/startLottoReveal.json | 8 + socket/startRound.json | 5 + views/home.ejs | 136 +- 33 files changed, 11525 insertions(+), 138 deletions(-) create mode 100644 .DS_Store create mode 100644 private/config.json create mode 100644 private/leaderboard.json create mode 100644 private/me.json create mode 100644 public/.DS_Store delete mode 100644 public/api.js create mode 100644 public/assets/.DS_Store create mode 100644 public/assets/live-games/live-viewer.svg create mode 100644 public/assets/live-games/logo-dark.png create mode 100644 public/assets/live-games/logo-norm.png create mode 100644 public/assets/live-games/logo-sports-trans50.png create mode 100644 public/assets/live-games/logo-sports.png create mode 100644 public/assets/majorityrules2-derivatives/.DS_Store create mode 100644 public/css/debug.css create mode 100644 public/css/liveGame.css create mode 100644 public/css/schedule.css create mode 100644 public/js/.DS_Store rename public/{ => js}/app.js (100%) create mode 100644 public/js/flv.js create mode 100644 public/js/liveGame.js create mode 100644 public/js/schedule/api.js create mode 100644 public/js/schedule/config.js create mode 100644 public/js/schedule/debug.js create mode 100644 public/js/schedule/player.js rename public/{ => js}/serviceWorker.js (100%) create mode 100644 socket/showToast.json create mode 100644 socket/startLottoReveal.json create mode 100644 socket/startRound.json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..73bfe14a340c9a06aa55adf3b3e3ed04fe48a6e4 GIT binary patch literal 8196 zcmeI1&ubGw6vyARX|ri71XKtjvM3&efC;5S@sh@fClOpxK_zChOS^Qlvt&2Tp#*Z) zvv~99LC}Mz9y|!*NzbCxgMWi(55D=)W+!P1_8|Uv12f;r%zLwMKgrJS+W-Ko_q-}V z2>>jtLW_&o98ko(s1s#Ij|gXm{s2wr00$3x5KdUr01+SpM1Tko0V41x5Wsu3DAttw zzM7?$2oQn)l7QGBY^*|ST8B#I)`5*o0Z?-|EDQEA50E~#)|%F#Qt66os_cPjSEf@8 zrrdGf7UrlmtwW{C9hhQ7mlXEiMgth@lGsY(WcB z@Qr98_kPkM8{>;7YagF|kui>~)8V7Yrdws>QQITTV>~@@@!dxNZMUDqn#YbChe487 zDxcWQY;JBoZ{@8;>w&Yu`%c&U=xUNMA=ySOu%lES9#nS63=!yLxG5P`0sOE!)e>mBFB3ojiB(^3CRE z*opWf0TH)Ky`{o2^?AR2j6LI=48qo{Yvc1-zTeNryXU`3zQ!6^y3=e7whOih$XH{` z=|&-s)^S|KJ`V~0e%r7KKBWH)_slsN+=1O4Kj$p>4};eip6+VynKiQ9r`Z_Xp@N4o z*^Y6a!z(X9=KZmq0+wE)XJ$4V-}5s&r<~6+KEq;k%^hrE##Ypi4|M+*UlJ7}a0CLg z%BLjq|EtsA{~uvxav=gl;BO(oat)_Z$7uH+1jhpxxwehipPJU8QXIiTF9IY6YKXvZCGZoKEi-Wd literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index b9457ca..969cda6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", - "nodemon": "^2.0.12" + "nodemon": "^2.0.12", + "ws": "^8.5.0", + "wss": "^3.3.4" } }, "node_modules/@sindresorhus/is": { @@ -51,6 +53,15 @@ "node": ">= 0.6" } }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, "node_modules/ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -106,6 +117,15 @@ "node": ">= 8" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "optional": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -424,6 +444,12 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "optional": true + }, "node_modules/defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -519,6 +545,59 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "optional": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "optional": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -567,6 +646,12 @@ "node": ">= 0.10.0" } }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "optional": true + }, "node_modules/filelist": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", @@ -648,6 +733,22 @@ "node": ">=6" } }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -699,6 +800,36 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "optional": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -767,6 +898,16 @@ "node": ">=0.8.19" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -891,6 +1032,83 @@ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "optional": true + }, + "node_modules/istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", + "optional": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/istanbul/node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "optional": true + }, + "node_modules/istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "optional": true + }, + "node_modules/istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul/node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "optional": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/jake": { "version": "10.8.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", @@ -945,6 +1163,32 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "optional": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "optional": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -969,6 +1213,19 @@ "node": ">=8" } }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -1074,6 +1331,18 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1087,6 +1356,12 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "optional": true + }, "node_modules/nodemon": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", @@ -1177,6 +1452,23 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -1215,6 +1507,15 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1231,6 +1532,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "optional": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -1353,6 +1663,12 @@ "node": ">=8" } }, + "node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "optional": true + }, "node_modules/responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -1450,6 +1766,24 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "optional": true + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -1582,6 +1916,18 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -1610,6 +1956,23 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, "node_modules/undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -1690,6 +2053,18 @@ "node": ">= 0.8" } }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -1701,6 +2076,21 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "optional": true + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1717,6 +2107,54 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wss": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/wss/-/wss-3.3.4.tgz", + "integrity": "sha512-WgVZercD6pVUwEUjFSUpTE7UoOGYAQUwye5VoSuYyPH58xZKfvCEYPTbdGdqdILMnmhSCPoRJXhgsSKY3CmbtA==", + "dependencies": { + "ws": "^2.3.1" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "istanbul": "^0.4.5" + } + }, + "node_modules/wss/node_modules/safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "node_modules/wss/node_modules/ws": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=", + "dependencies": { + "safe-buffer": "~5.0.1", + "ultron": "~1.1.0" + } + }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", @@ -1754,6 +2192,12 @@ "negotiator": "0.6.2" } }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "optional": true + }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -1796,6 +2240,15 @@ "picomatch": "^2.0.4" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "optional": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -2041,6 +2494,12 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "optional": true + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -2115,6 +2574,37 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "optional": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "optional": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "optional": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "optional": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -2157,6 +2647,12 @@ "vary": "~1.1.2" } }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "optional": true + }, "filelist": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", @@ -2216,6 +2712,19 @@ "pump": "^3.0.0" } }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "optional": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -2255,6 +2764,27 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "optional": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2305,6 +2835,16 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -2393,6 +2933,72 @@ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "optional": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "optional": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "optional": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "optional": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "optional": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "optional": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, "jake": { "version": "10.8.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", @@ -2437,6 +3043,24 @@ } } }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "optional": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "optional": true + } + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -2458,6 +3082,16 @@ "package-json": "^6.3.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -2529,6 +3163,15 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2539,6 +3182,12 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "optional": true + }, "nodemon": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", @@ -2605,6 +3254,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -2633,6 +3296,12 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2643,6 +3312,12 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "optional": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -2735,6 +3410,12 @@ "rc": "^1.2.8" } }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "optional": true + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -2821,6 +3502,21 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "optional": true + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -2913,6 +3609,15 @@ "nopt": "~1.0.10" } }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -2935,6 +3640,17 @@ "is-typedarray": "^1.0.0" } }, + "uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -2994,6 +3710,15 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -3002,6 +3727,18 @@ "string-width": "^4.0.0" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "optional": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3018,6 +3755,37 @@ "typedarray-to-buffer": "^3.1.5" } }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} + }, + "wss": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/wss/-/wss-3.3.4.tgz", + "integrity": "sha512-WgVZercD6pVUwEUjFSUpTE7UoOGYAQUwye5VoSuYyPH58xZKfvCEYPTbdGdqdILMnmhSCPoRJXhgsSKY3CmbtA==", + "requires": { + "istanbul": "^0.4.5", + "ws": "^2.3.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "ws": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=", + "requires": { + "safe-buffer": "~5.0.1", + "ultron": "~1.1.0" + } + } + } + }, "xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", diff --git a/package.json b/package.json index 78ba748..706a710 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", - "nodemon": "^2.0.12" + "nodemon": "^2.0.12", + "ws": "^8.5.0", + "wss": "^3.3.4" } } diff --git a/private/config.json b/private/config.json new file mode 100644 index 0000000..55223f6 --- /dev/null +++ b/private/config.json @@ -0,0 +1,27 @@ +{ + "applicationName": "Majority Rules", + "applicationInfo": { + "name": "Majority Rules", + "icon": "/assets/majorityrules2-512_x_512.png" + }, + "debug": { + "enabled": true, + "changeApiUrl": true + }, + "schedule": { + "scheduleType": "classic", + "nextGameText": "Next Game", + "bgAnimation": true, + "invite": { + "enabled": true, + "btnText": "Invite for extra lives", + "rewardType": "life" + } + }, + "notification": { + "enabled": true, + "allowInBackground": true, + "requireAuthToReceive": false, + "provider": "onesignal" + } +} \ No newline at end of file diff --git a/private/leaderboard.json b/private/leaderboard.json new file mode 100644 index 0000000..a56f1bc --- /dev/null +++ b/private/leaderboard.json @@ -0,0 +1,9 @@ +{ + "data": [ + { + "username": "Alan", + "totalWinningsCents": 500, + "totalWins": 1 + } + ] +} \ No newline at end of file diff --git a/private/me.json b/private/me.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/private/me.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/private/schedule.json b/private/schedule.json index 5fb9b40..8a61ce4 100644 --- a/private/schedule.json +++ b/private/schedule.json @@ -1,10 +1,19 @@ { - "isActive": false, - "startTime": "2018-01-01T00:00:00.000Z", - "nextGameText": "Next Game", - "prizeCents": 500, + "isActive": true, + "gameType": "mjrules", + "isTestGame": false, + "isWinnerTakeAll": false, + "startTime": "2022-02-13T20:00:00.000Z", + "prizeCents": 0, + "prizePoints": 5000, "currency": "USD", "display": { + "title": "Majority Rules", + "titleColor": "#FFD700", "logo": "/assets/logo.svg" + }, + "live": { + "flv": "", + "socketUrl": "" } } \ No newline at end of file diff --git a/public/.DS_Store b/public/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2a4ffd0051f7457cf33dcaa61944d4385b1a6928 GIT binary patch literal 6148 zcmeHK&59F25Ux%pyB&iv2N(A^Al?E_SXK}(V~j80_yhhBXEI@TbkZF%6N4;)IqL)X z20nxLeE|{iAYSz9#TO8)>h7?ajN)x^r7LuQHT5%9^Feo~0f6=ANe{pU0FHyuIfv74 zg#0vW(lC|_h)lhsfIMF0(>RlHE!r9^1D1h*jR9J_TM$8xzcEzT@4I-KrFr4|pID>m zw6?bSHt+B!;h|iFMO4i5el&YTPj{uv;*}o7_tWuW=w7@fMG>W9JW~m2GRBa{4^olH zMPJTElB?WMJ9wM7hwkpt(e-`5>-DbfFS{PPy>KKaQx(wM5u5&r91P5!#XE1lf4%bM_+~vO`D@JdaJ|kCDp%>_ zMK}|g6bERh-kUHY-Yea~rH?0`^}dAj?dONjsxOl_ktZG1y_H_T$Cp9_o^4cXjgD9L z^;$0<#&7Rw4ph#1rA=R@PU}6@v2r#TFzbhR&PKboOUr;|;1n64{lUXQ7#J)ys;vVj zbp=3l(5wV?mlQsye>k zQ{lh@jdr#SSO%&LH1(rP=l|_L-~X#g_Q^6}8ThXlV9p>M^zoC-*;@NJI%_=~PjQe? oT&Yo|;ADz?gQZ5apx8eGiUvDb22PcMUtiRt_5c6? literal 0 HcmV?d00001 diff --git a/public/api.js b/public/api.js deleted file mode 100644 index cb30952..0000000 --- a/public/api.js +++ /dev/null @@ -1,32 +0,0 @@ -let nextGameText = document.getElementById('nextGameText'); -let gameStatus = document.getElementById('nextGameInfo'); - -//Use fetch to get the json data from /api/schedule -fetch('/api/schedule') - .then(function(response) { - return response.json(); - }) - .then(function(data) { - console.log(data); - let schedule = data - nextGameText.innerHTML = schedule.nextGameText; - let startTime = new Date(schedule.startTime); - let startTimeString = startTime.toLocaleString('en-US', { - weekday: 'long', - hour: 'numeric', - minute: 'numeric', - hour12: true - }); - - var num = schedule.prizeCents - num /= 100; - num.toLocaleString("en-US", {style:"currency", currency:"USD"}); - - gameStatus.innerHTML = `${startTimeString} $${num}`; - - //Set the src of the image in the gameLogo class to schedule.display.logo - document.getElementById('gameLogo').src = schedule.display.logo; - }) - .catch(function(err) { - console.log('Error: ' + err); -}); \ No newline at end of file diff --git a/public/assets/.DS_Store b/public/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..916b99173b8daed375ce71254682babe0b6cf431 GIT binary patch literal 8196 zcmeHML5tHs6n?W?-PBd+L7{jW5pNY+msLbqVyq``M)aUk6H~g;BvYESWmyXGsuzFA z9z1&U;7<@dDgF$vzBe;!yKO-$h^z0x%r}|$US{TdL#A&E0KywaEr2=zI9Ld4n^-Ln z(o>m}HQRF%QJ_D-Md(2QDRd#9v*r$FfEi#0m;q*h8TcC*z%!e~S#s_hE!WHdGw@$B zK;H+6h0wKF8q}W-taJ*1Six>B*v33S`$&tf#nPa5#dn(QL0DH|Qw(9;Q7_3H(Y06_ zH0~gbI|w_nuo;TbqobeH<{(^yTr&gAz&rz#yPtprVi;l8K9#?R)K1@2SrNopcc2~O zsEZ~K@5foB#-18xQLcS`qj0KDwNtC_?_b+)He~C{_M{=P-D=3Kt>$D>bbp1}} zS(0Yzg;|cUp9DB{Xn8M}tu5)b{3j~y8~dGe%j{CsZd(qV_Xn?Uzy18~#&X-}r)~SY z)8p%DER4a(A7qKjdN?Mn@hsk~1n?9T3@}~=>>&;@c68fv8Dke=i!>v&Dr`jaecN*!7e4BJu+p4T^<$s>?z?98k$8p6TWyaV+Gq40654apqHD1< zNGj6nQy7uYeLayer 1 \ No newline at end of file diff --git a/public/assets/live-games/logo-dark.png b/public/assets/live-games/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0a37f492aad8e54b69694f8bf8d065ed9226641c GIT binary patch literal 1791 zcmVCQJW}U>ZlarG^M0|(OewJn9 zi;Ii5iHqFHQWo&|_;|3hv-3ff@%j0Aa(Q_S~gr#wG{V1gHd=D%hl;+5k-%Y%)+sqtX8E?(P>1`L6AdhK+p% z=XGscF4p}EsOVI8JRaZ2YG_rx1iH7kN2he)(mtSmN0e}Qetv%EQr@==_nqGv z!xm`AJK+@W@I9Nc~*o@UtBe`tYLM6 z754vA*<4|Al4a-=RrWWHfY*bgc^jbn_waL%gA!S;p|Q)w}d*y zkALZIfPnWj2e^^<1ifMaRRp|ycz8Gr4OR^IPiUuC1!E2sof`w(n>EDpkaOEpJsxBh0ILo%$?Di>lVt_ zBUGxgc8*=Hfc6T18@k4Xx&+BODSdzU$rI2Sp*#~hMxh?=eGfLHjPWUA#Q$uBr=V~K zM>aOA381o1E?_a-X%h2Q!(GGd2%0*c2mjF4XB(*EUgMayNuai1#mtVjlX+a*>yS=e zLY<;MO^9m3&YiG%HBPhb&Fl^xYK0O-(7Gyg^T-5Kb*=s&G~=ODh}1Ah@Un&##3F6Tr2nKY};? zi&iL?P}J@%ZKXt5<-4@o%7pv+38N zU&$8PLXGffwosdb%J>y+FYRHCAWza&V!7njL_i}=-6mRopj4MkR>3uenxm3d=LF#G z|HZn#(S{2ns3~kPGZ}U<@6pZitJ*Vyy3Gl6IyR>ZjiB<0w0%`THy!oTQ~`C0?^f;$ zsG5$3fZEz6>~;HE%W#c{zsolEn2w{)y45W`ChZzS6(*o{87$kOPfk`)TN+v|W%k!; zs})qCt=eOk>l%{3Gu}hWY=mRz(}>CN8QSY34Cysy0cY*O9@s`Knh4WO00 zZO|og&V2CD`ZCYyGrDX7eigPgQ~`raE>?S4nbgHJ?`8Q(i=**8uVhu9Mq{X*V`vt5 z{y29pFW3DHHnFJ}R2Fu9`T$#bGTQ@gB}~f7LuOSco>vWJ+c3%-s<5q7e7j5rRvu~- zQ{o&Q+Vb0TvJ;$NG5Jf}|J<}0U_0+tfvf_{%FbJ5ok~R}D zCN;SumoenB4u0bvT%gX@@<&D={_wNE`gx#3GC*?c7_%LbnQ@8p+!=r4+wnS zh?m_ZNYs4|k3Nav(QRNi3RM-9tF>5S;rmQD{p6d=x>cY#N5^kW%S}0*Mb2PahpjXP hn+#M_fj8m4{{di=rFb?||8@WX002ovPDHLkV1g8nUt9nH literal 0 HcmV?d00001 diff --git a/public/assets/live-games/logo-norm.png b/public/assets/live-games/logo-norm.png new file mode 100644 index 0000000000000000000000000000000000000000..324bf5a48237511b1301a24767bb72cbbe2619e0 GIT binary patch literal 1697 zcmV;S244AzP)YK!VQ&=|o-i@sHuj=EWPj3r# zuYdmN8Q8&qrB2Z@5>Trn;foks)F6zzW1VXs3=0+FkRK}Bl56gffsO*!>_OmJLkp5m z;yiua}zQn`bLN{swDMT%*|O~Gng;UIB?Btwm$rpyVuZcXXRWW5cN z;HgA9#lI|6goR`PLw&X;u}Xnj{g2*d<`iR1D&{n)YA*$KdxXjli5bA8qo}O&Y4^WimrC%@47$nAU6XTMd2$D+H9m)JzYyBDQ4qfF7X78=~UNJ*ZRYp z0mK8P#c}5ELM2z@(aK!n3A9#etw+>zS`|;zv}iU`PGTy55LEs#X8`eRzj60Hx|X_= zykFvF-gJx40@_;UcA;*CXHKi)Y@{{ww^&rnCWn={m@pqj_ceP>ulP^n&#il6U7vRtkF^{GJbax}~Rjiui5BkaL*tzEb=mby~o*kkNxE_$Y|fJPwb~P(nfS)q4F4?I z9AqYB<>uF|$Is`0Mq8?Zy47du>gt$4o3}v7`$|6&{{T>%{$zSraKi7xPO(%rv3cYY zdzST}f!=lRv>7xvDpp=s6xPX2;%k<=FLdk@Z(eY2ng!KZ>n72ynCLin)EcxSGX<^} zrjhG?r&CeWol1uyVlic~ZezOHfdtQ-5k3Kng6h}ib zfY`!~;+r~7ZhnZMX!o~5GhaGGSzfzg(h4fX;Lt&u_iX_hw5!ykK-PD%Btu1!%t-(d z2VFco3x+#%2MkOm(RI+B>aX-x`rswWB@3znyVGax3=Ui-83x49!Np_|ysZexO>o2h ziewJ!P>=BSl?~N^EqMR~s7z?cYyjKG7|vrI;w7$a<8CI)ra5sGpuMp^rh`&Y8RTBq zSjl|Mm{RH%1KJotiUxgcj2m7nShA5_DHg?`nlNx}7F*Op?M*2P)d5RPOvzzO8B2(q zPsHRBF|^xRaj3Qfg#$KCwz_gQUqaxd)Oo8$o7`F6*YRjjjn%I7iPhFJf#L2fI*P^5 zKCq)gb*vVP#d4>#+GfjfEbDaPUIeNWYXN&{xWMc^@|Y4gLfTvms$;ce2!P$_%H8hs zjgd(R7w4;!4j~{)*10%TS9!BSVpYVI8+QRo{03z9swfBYq)y2bwiH rJ6(HS0Nh_9R)&JE25P9n*HG_&;r~);0<&=^00000NkvXXu0mjf^=?A} literal 0 HcmV?d00001 diff --git a/public/assets/live-games/logo-sports-trans50.png b/public/assets/live-games/logo-sports-trans50.png new file mode 100644 index 0000000000000000000000000000000000000000..fa50b80c640dcbccd03025d79c259e9494ff76ef GIT binary patch literal 6265 zcmV-<7>4JGP)diLXOyIm4XQ^ zRz6RvMvPW$n`){76Jr}iMH8v=%>k1p8legSL9!bVQR4zxK$ChBut`p|lCTQO$Ii^# z>;8J4XJ%)2XV_h`KeB&jXZD?U-uHU0`@XOHx}Vv^4e*~0=^0}ZSD2MKcYG=D9vu0r zt#=OaOLoaXzQE1tnUhONenHu}a+c(>Qj(NQS+;c4uUoGf$k#n!LEV`C>4+q0dPV?E zvN8ZI6R^%@nM;=b)t(nWJ5Yfgkf3f#Pajrx$E*jK#}lB$P-dzD?2>XZORl?o&-0HC zL|_LTs03&RK*3A}R6@TDAn_VMf~f$QQh~dE%%08P7-+x_C{PVhVkiTc5TJR_Pyk73 z0O9Y-Wrx@CcjuDNjeXNpH05_)T2@wA05ON1r?A<;V8ZW3oD(I3?$j`*D3KE^ixNn|g8kH|X)G`~*M~ zFq9bSG6poW94f#v&?39wlBOdc{-iER{_Og2r^f02O*|k-2T|&qj7Q1rDtscSZA_qqR?iBq6h&%1D0eI z1FN#Cx@d{q;`i@8Sjxs~#j#NwL!R`{U_G-HwCr=C8W3kAbCdFC@Qn2MBN` zU9ZYJxefqIdU{dYyvxDVD`x|^f2?FGZYN@H&Sf)4wy(USuV7_BT{0{f#AU^Zo%jb^J_R-wb0a0IUEsFu2^3xeTmb(<_C5etrgk`Xc8{6Y^Zmx!44m zq@5Iw4L~!nR;+3;lyk2#oI}&?%=TrIdkgIJk6bmaoa8^v%mhFLs9gtzyybMV_YLsJ*xm?5m?D`c)!rIO08B-wI=Leujd*+0Zsy}1%L~fi12%$0T*TygAq?a%e7X&F!lKsn^4_*9xC;ywvb zV6Fig7a=Q30E`xZZd5uiebgJyaGa$8ViJl7rvzArD{kHO2$Zn~g- z^8;O7?29l+O0KEZ0Oexj^`-(G={&hWD^?WxVxIVF%S9;w>Qe*VAfFc?^6{i|qoRlN z7EA8Y+jcFV)z!7$eDe6=`KJ88;{7N1g%Q9cSJQ%Vs3W43p)9MkxE?5#uUp>s@c$`O z$F9Kff5RoALB`VYAX&???%>$r?b|BS0RdWc1@!azA<_}ijdwChmEkP_f&KicS5C!3OktIwa)|*HV}~P1 zUbjf#4l3wWEZ~1_n=_8i%b>1LM?(R)8C?U~Gjs7?Y9gkd+uq7Wi~#L$P2Y1#GDJEK zah(9LUYH4ZFo^YObyZh@f*v&cPZ=3C0zNlO(L!-jSq7%7{2_2?!8oK#?%pr`1}eiW3LDXV9Gh^iOO7WZ^kyMmdz;PpOGC6fJZP2hp15A@A^*<#&90+t+7$P@B`s z$DsTy?;P?+#M~A-PuXP`3bVBM_*@s|CaLZ2p9G+fgKt3W7PCf$JUuUIj<*P6JuSsg03~2~;j-q(x6PRo zfqEHaRn~*7igRiA%*6t+3^Im>&d2OKD=y01sJKKSE=53dY8a_hR((A_0BtR!GPI(> z5SI%b5CCSQn>sna0Gu);ms;lr#O%4HAdUoKC@mN*KoPPKzdZKD)~`M8L8V`s(@SV! z>d2|}04l}B%MWv(SWbEKBNFl&T0tgNhPYMvDuyDpa88v@Op25A;LN%TfK0}LS-?RS zT#6aJp9^Bpo%9?GMJ{LEYkD-uDgdesMQ6vrc4XPCC%1n6r7BQAxf_2US|6~r%`TaZ?p=~*bC4b_OeI30F^-!%J@+xE29M<(Vt|_P@0Tf zC()U6}c_4{{T2Q0t5izNX+D1NzY9WGjPOEYBht-^>$(`qb!F~ zBCHbptO~SaZkVAu)qQ2vmf2tF1nS20q7i64o4e1cotax9$o+6G4&i8CAB8p>&ox{p zmRH)L#6p`HNlGoQ#=J1nLB&Qf(u(9r&E1w;Z2>goHMep+Dg&dC*CNO%!5C_-bd+m3 z=a!Q1tlV<{@)}GXk>)XusNDe6)~h5-j6rnakQVIF2OH1iN$Am~+KN7{wDF|+T5hWV zlv*LK=GxIjA?yKF1`42Jeu!Ms+{dBkbEy9uDSq19SG!JZqLAPh9Zi%9E|?TKN)a7p zH}B~!_iyY3D!s5V{mVLK708do;cwhp$S^C?& z3Q#gB2o8MkHMw(Ap>G`(sexF9Snpo#i;8KYofx;)LJVPk+?tvyaIRR&-LiI1oP#2?>paw{+gbP##kpNaE#andP>eEoH05B5#tOKpruX3HFwGIBM6&DYvx>MFU zN$(!qC7m2_2jrPs(-+ku#K1|%L^+hM%XebRWMinhQ`wv4ebZW7=e}DL)D7u*i*dfm z-BL-oR>ElNfT$=)G0`GpjNzOr4CNM6 z8v$SSRYnoR1ei{~sLsS{yG|7y9Rn@Be^DRBWO47Tec|5g4bY0}FX4YKjFoCxRjF5n zQMxlE3RUliDp2v1vD&$3_o)Zh$r#G#RkKBVcJDfIg|<$J8Vj4cYVl&m@+?V1x6&7d z-t69W3XJE4qx{S*si^@5xRiTk{Y&@U-3_RJF#-!x!vm12ABJ;UjDiziY0I&jBe|(! zDjLhJcxoykFDZqSzoZnNVO6+JzQf_0G@q4xQ^}3m8Y@G?^fl_?t9()4dTOX6U9kxx z!rvHN38WM+6fqoF%q7n@zi`jOE?+sEijSlYwez&v zON0PGQ7Sr8iBbTrqob7k_lB45ezHqY=?~APXLlN{P%#YdjWDUF-FO!A9>8GyG9xQo zC(lrmW6Dq@Q?EbcPDlm2=~muh&AL~Fd{4e8x6E3MBv%L5i3)2BB&h^qqb0N%q%^g-bc^Pw)4Y68Xr4^ZaK?SkM4Jpu#Do*)$3*lAD?I{!{K$> zkDx$ugTbMar=2ofyy(1p4kgJ`FTVKizv>ax>H~iJym15u%uedYFMZ&?Z)|wFl0aMVWl5rO?@m>J@1d#u_cL5+u;gSIVlHI-lklg6$=Ht9$v%Og!pfH`WwBc zi8TyMkRC--Y9!859 z*wv3_YS;TZ*EDJi)C}+LeQb#6m|HvsXw1+mm&irZEkyh}z9DE016g%4jZJbW++0LS z$C3o&Ss6DZc+N&M6(g6FP;{*`BkjvBl~(=otXGzesE62ffx0UF>`YwGjCz4!*D(UD ztM~PEK2`_}jCEFd1&;Nx0?Lg@c%9`GJvTrTV8XLAeqB1f8h~aA3ObFOxz!awyeO< zS0ycOj)743i-FM253h^ytovX~Buk?l6-^I6c0f`QKC0RHFR-Au4ZJO}F zj`?r&DX6Q{N!S0oCV}a&W%a=j>QAu^vF_n7YDWm^$$$fN_8Sg*@?FiVQu% zrwq*Wxz&mck8XU`76xl>6;nkSO~+}q7oa(}igzHYK$xy6M02fQKz`1V^PT_PvH0OW z2X!^JvFBZGS6r;Ds5FvG>HW3dry(!Z89g=?5zC?K4}_|%xlz9vh)~zuYI4b@qb9#R z(B7XV-$7J`=1_?c2E3$SKN7jcK5O~M>Ya1g*q_}Rggnds=E{iVGO%Pkzmg; zP{E%i07TeV0*X*qA+Hk#(V?m;Xd#ONqyVbB|2QS6%~wW|>~Pt#h1(Z4^v@dV&Z)Li z_|gS-OqYiABIK962j3Goge~m=l)mJvIh04)B7dYfNhc+n(>e+IICMp~>ie(&0Q@Zg zc>_ZCL{$4PX(aH%Fp#{ZNE-$Q77JywF%5ZZI1VNqF1Ec{yX~JIwxXz-g^r}|(BzYT*U9@*!wsdCI zcT&H6@)a`?%9qki%NEc^FCwd`Q`3#W)^H$o97+mPm*U$djX~Ogq>4}6oL&mHNp5Wn z*z$@&E}2^WEfzZW>fb+m0&?Ol0PX{3a_EhEeJaIAguS$+EWh4Do?M*mcS~x0UGk2T z#$4(0P19{72Qyu#v;wF-*Oa6C2#`*eFKU}RzfnLNE>xAkeiC1pDDf7ddU|;sdxK^9 zt;naJ8QH$A=9k)5oN&$=h|lxTqFw?ZP6xvVTZiOjSLQaOsJ)CW;cGwl^R+M3y78~R zZ}i~9Y2jup&}B&0)Vp)58hZmBW}XDo#sJ?}bca6EXfCzuXgK`sjm_yO_yO70dUUIP ziC8y4aGSUnOL6nay<3*m%Y;XM_s@o0ySMeNdXB&Iq|qPGTwyu@J%x&&2UO;4f%ziQ z05tFJ6BWQr&Azg@ZT|E1d{(Vvju=!r*@pBJkXU87SG9F(tY_7A^1VBoC7IiW{quKS zy5|QCNtUi|_NxH1nB=bokRPMjz6pHqKFM%Uft2Ye$tLy&IA^m8cpl$`_8WMQ1lV4I zD!^W_7z;hQJEPiqcQKTM{~3xyvK#E3bGRe7`fvAc`rk%wWajT(a{S;SO(Rg%KaQ#C z)}?Lp(Tex(r`JrS zk0;Ifjyr~2EZx~6ssKOUD2`=|+?d}~Ce^$`hX#40#!2K-nPIKwh`3JPpcWk~J5S<{ z$$EUV{Xkpo%y={0ek^dG0NShSU%i$h=5zG5A!aQ3UuKF3lWgP>JNi*e>U;7q8quxl zo`KeJRr{j4xs1Co?>>c{D`+)+)#sMiJOeBw_xR?f3U{o~wl%ai^Q{xrZe=qk0Zr}pxxxMS;84{fNxFxj|5S)27oV|^w!#teNGgW<2 z>%^GZ-WIIRq2!C2@5W6Z=li#u1|*# zEf$)-g&RNJ%O`W-t=CptFK$W24wR9HjhDp)VNcbYDmup(AC_Gz$=!agPesdYJUJiy zfov|Uyl46Soxx%PCxD5s|Bd9?&ea7FG>qR zfSRAmfT}NQQ&2y)PLih&B!}nr7dvBcj|!;tf!{`(*)(X-wI!Fo1}r?z#>n!`YIXE= z7#G=i{%be<&luDX^*~0xsOeCVW))-Ywb*sCY<``S(7s^sQ3KU3mcT6y8hkaTnB%~# zKMd8K)Pn6#<$sT?)m?^ixOQ$VxB%gOMLa z=QIjk&nN(VnoK*REjjxCQrYg4jmNUHB%arMr{4V%;BGACb8EiVz>uzy>#g_Lqt4W> zF6_ZS8u0;_A9Na632^hL!uU85%ss^e8XL?>?tj3>x6uM`Ih46q4;4yV?H|I{d*l6i j+<*bKKX3AApZos-Vw%|C%CQjw00000NkvXXu0mjfhI|B8 literal 0 HcmV?d00001 diff --git a/public/assets/live-games/logo-sports.png b/public/assets/live-games/logo-sports.png new file mode 100644 index 0000000000000000000000000000000000000000..039696123085e5d4b036afeaaf2414f8b0237de5 GIT binary patch literal 4259 zcmV;U5M1wxP)4|=Dx zY6^k)ejt_pXdIPRNc|C~{3rt2a}bn}Bb={%6cv>ig^)l%c1ZJ~d^!n*NL9fnfrN@^ zeG)~RKN4l(Xm19_rQXBhgo>%7ubOW^#HjlZ==O^%fQ42Kq-*)odL`&7XBXl{)dOFgJ`h>2dW1s zRsrf-Ew^0T9=mk_fgLDNkAQ{Ff`x)rlAz0nEtXlXiS4m99~>MgiyatHPm(|-~M5vc_I2=$`uLy-b$<5rtf$+xua+xJPzF_&~@6Wv76h^E?DOnpf*@2 z&W8ZyL5a&LZm|F~w_q-};J6KV58wX&!U0RcoV(cGWM_<$Blj?_K7QuOG5iWy|6dnS z7E_Vcwvn~*=JxXo!czxG{-mAS>&0bI9I-3?nD%=!rAi zG2TPgwL!29F+gn>Sm(W#MdsLWyXKhme7p{jWs~r9iwUmnxxU{HEER}LZP|7ke{3!t zYd7Yt-@m-_&JEC)iZAngRkHo`6Bxfr)-?dYRRKUhAW%<_-v?1<=sU3dz_w+y>cFU3u+V zu7T|GaQmgc<=hNV1b~X%=m#S$%cWYC>s3YY0!nC}H_i`lZ1u-tOJ7|#VrLDSGK1V> z!7~V`ZJ_DusfiqL>e@1Vyop;X04P#`KnYgEMmAXOo}LuKA@YqfbZV0paEcT)+Opl+ zfGoqB9lRKT?Tx}pSKcv>FfK`%oolJ$I65}k_tfca1-zH6Er6BQ6`U#pDh4qC_Vunb zAuW(t2%fehlhnaRbZNC-6;f8k!1%xg0BWVyOQYS8*RQ{FTYfH!ClSu%gK9%XJwORt zo^C!~!gaDX*Fl|k)tnj%UJlTp4ysfk45tVN4xre8z!a84;SS2K<>}M}mlyS{)Qtt zaw8;j@gOEIX#aGs1n;+3ZS-JOC7DjSO189eOim9?cvsq z&!Tgq%iB#!8&W{$&>~hK2}Vm8yrlDDQ&HKXC9aLst3qL0u>1~Gw#xr{A(Yts=8D@k zL4V2$PFCn-zZ@wBujiV7a`1Hi_d2;16ad;34QR6E!nHJs7+cvs?gTLoC`3)-Tpb81 z(a}E!z_fbR4Tb{exd5Tk@BaC`<6ZY&u{LMg24qG!AIZr9gOJ*B&q2n%zn**qg1!rC zo&0bF!q1Md%XekDz$p;MkX?v(A-|HJoB*gT!{fY=5Z4HXkRSk+v`ri5A=PBTNTQaY zI*IozkW*8CYd%^OK>YzAY$wPnkxSz(*U<+mftKZ!1Nf%H}9U3_>KZ-?e4XpcavPhl5{2q7m!zg6dGpKS8!x#`0RT;>b$@ z)SCjbN>{fs%VmHDC+UK+rhk?Z%E$m$RQ!9#7^>2nG=`F zMy9AdxM%=KDa)k}d3}K*BXjg>SVx=4-u&{hiWB(*mRcYggy__YB1Ki}RZ7Xc0-vh7 z6i6kV2a{@GF`SpECe)c$SZ*omrO_$y*vm)%SPg+nPwXe((v(#Y>7AM3bOKpQ0kt!% zz{(VjNx;aelH1>~0rZ%N*v9alV-GbVK>a3sU`I@?_!dkr_5e+pdq;AkcOOlcjY=J3 z^=d*29J{_CTCbj)vo38kD_-40T1@c|Mx5th0V3M)ZbC3CEb%=v1($i-y3^-`^YMb=CGs+Zo3 zK#VGJ^>iRHPzF_)LV4}zLtf;U0u|%bYYSkhiW&fm`d;}?8C1H^d5J+Kab*ev=0c{Z z$e4Ql$OFYlOFckVvpC;NQpI-Et9(M=TrJ&>!Y`?)ZY^bw7ux z7r?`4%^_4ieE9xWBB;RzpB|@2Amsk(Z}I6BpIYhy*npO$?jpa)0}H_#R{C<-)p^eb zj_2b%EJ=df!de*bTj?P?X6J;z-SfP6-ZgNZ_gw0=>OM}>ECRmtM+xWXy&gRKmwh_V zL<`iN8HBytEqaB0n$FsTN%z{FN>Yn5gTL?k5h2 z0Tv!OPfvO{9``16?L9|?v|Kiuk$mwbO7)v7})|@s_H)&!Lq&Df#3nu6g+_0dH6T=@Y{bb zCPOOBrp7hiMefSOt=*bHe*laF7M2QmF6UX2XIW~1_zDxrV%-@9$)yFrcp1_GT)Kal zN?>wtV6OvrXPK)noG7()-rObZ@*D&Wv+;@IKe&1q+D?Cb0lW!1;jkl-Kish;|~E za!Us}wPou+s*&qjgJ5fex*L|UXOQu(7?gSqM&g2va1e3jjlgw$)-{SF{qsIYvIihj ziK?A%q5kwXZwGw3eB!NY;)-z&t~RLjf>+2-YXGFPI5;Sq_;Hdrd}{l#~*t3eY#x+uq!+?fR+QpEiD#{Gs2d1-N* zFXWSgkE1hP>7=J;eQpNV-~7azPnLE0G&QL70@!o`E2hmMd94+bSvvX?+D&~1_6eMa zCGEgj%X$~|LU3}a0)Uu--oOvq;GCJsO!`2|lp=Anq)UC(F_$qftv1>2Xx&#T_op}A zOGe5-0kDuQtXDOFow}}lyh!gu>$d-c-Q3{%>v?eCQ!}#g4s)w0P zwu$cdxsjp;JM}~h^?!>cobt*#7fo$Hv)$=$npbL2>tqC$a(7_L#a<%j`pH~swytZR zSQ_kH{jzI{mW|7nky#?@QceNd02pWn0I67LaV5CJ@4hdusltO=udEHkP)cVuyR>?C ztMhQuyi$WoZ(b+ggQv&1H65^4?IQR=ncyxKde7aLt$@vI82}eAky6x%oS$VtPK6%8 z%v3tYCje%6AL@NyTC>5*;EGazx=ZMN&+vm>2jeZ((-YbOx)A*TI6tdIfC` zyvwD?IE6B^g>K!xXZIJM(BH|*CIAZyFu2U}3)6DdNl_dL002DN0+4I4gSly$xJ9Q< z?tE{rGmWwB@|*G(x))1tID(;>`IuyYTE=6WZx$lr{Hk zsr1H7b1tS;EO%uKQw5Y<7^lS-N&I4ms@;OrPiM||`U7asoGLyk_ESg(-8SS{ECOT^JTuz6h=vDjuI>1)9*i_;y z>!#Sjw_b+or;52LU#AMin1psBMYv_X8LNW|)jqiVyn)K8;1l@yCCHFg1uO1;O38ys z{OqN}&^kZ`>aMJ?9jJPR>ZfSh>fn)n1KL;j4_a=WTvGyzgCC*6LtV{Y^5By&Hzm$t zNmDK%U|nuz{Qjby=@fg7^79&~qHbO%`P}TH#Wk=TpaWrgS*o8#&vFJco^B{5P(Ou~ z)+jyMNB*1_ovK6byS{L38B)s<$e$sv+!hQzG4)ibfUQ#(Rn$)*m!Iln%+h>W=e%-i z6v#Uuh*^t22b2ImHi*%X7^Tw{kljjy?t%!IuZK0{W!;%j9V1C<(-)nZ^d;iwJ0OQY zcL^%NFG3WdtOw;jouJ}Vgra^bEY)G{fHtNf{is?NsxBm$e4GmostEApuo^S5T0$TO%b67h2m+!YsFSk5HF$D7cim+m70*E(U_GaZIDvPSzpK}@p+ut z-6~SOco3BtnEhtwXE*sa>}CN#^hRM9pa}pDDq*F8%_l-}(mAPE524Uwq!2+450JuW zE}I>{kpWt}HMj#GZb0F>y{}&kL&#tYHXuZcB4fcvoz9D> zRBH>1b*JtuITzlwD!km!M_JEL&!~5-R2W5p=U?G)af8xgWNI$%)mzms;1kd^Z)Sc`~Sxx?lA+*z`tTZ)cRh(hp%MM*14CX vvsR*BqLNTvY4EKC4Sf`2E*-@!R4wS2WFWd0OM~b^;U57_12@dTk23HIo(Ee7 literal 0 HcmV?d00001 diff --git a/public/css/debug.css b/public/css/debug.css new file mode 100644 index 0000000..39c0ce7 --- /dev/null +++ b/public/css/debug.css @@ -0,0 +1,50 @@ +.liveGameView{ + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 100%; + background-color: rgb(0, 89, 255); + border-radius: 0px; + /*animation: debugPanelActive .5s;*/ + display: none; +} + +.liveGameView .gameIcon { + width: 12%; + display: block; + margin: auto; + margin-top: 10%; + float: right; + margin-right: 10px; +} + +.liveGameView .viewCount { + width: 12%; + display: block; + margin: auto; + margin-top: 12%; + float: left; + margin-left: 10px; + color: white; + font-weight: bolder; +} + +@keyframes debugPanelActive { + 0% { + transform: translate(-50%, 50%); + } + 100% { + transform: translate(-50%, -50%); + } +} + +@keyframes debugPanelInactive { + 0% { + transform: translate(-50%, -50%); + } + 100% { + transform: translate(-50%, 50%); + } +} \ No newline at end of file diff --git a/public/css/liveGame.css b/public/css/liveGame.css new file mode 100644 index 0000000..9d3d74a --- /dev/null +++ b/public/css/liveGame.css @@ -0,0 +1,136 @@ +.liveGameView video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + top: 0%; + left: 0%; + z-index: -1; +} + +.questionWindow{ + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 100%; + background-color: rgb(255, 136, 0); + animation: debugPanelActive .5s; + display: none; + z-index: -1; +} + +.questionWindow .questionText { + color: white; + font-family: 'Roboto', sans-serif; + font-size: 20px; + width: 80%; + position: absolute; + top: 28%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; +} + +/*Question Countdown*/ +.questionWindow .countdown { + background-color: rgb(255, 255, 255); + position: absolute; + width: 100%; + /*bottom: 95%;*/ + float: top; + left: 50%; + transform: translate(-50%, 0px); + margin-right: 20px; + border-radius: 50px; + margin-bottom: 10px; + color: rgb(0, 0, 0); + padding: 5px 0px 0px 0px; + text-align: center; + font-size: 15pt; + font-family: 'Roboto', sans-serif; + display: none; + animation: countdownTimer 10s; + z-index: 0; +} + +/*Question Info*/ +.questionWindow .questionInfo .questionCount { + color: white; + font-family: 'Roboto', sans-serif; + font-size: 10pt; + width: 100%; + position: absolute; + top: 25%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; +} + +/*Show Toast*/ +.toastWindow { + left: 50%; + height: 20%; + bottom: 30px; + border-radius: 5px; + transform: translate(-50%, 0); + background: white; + width: 80%; + position: absolute; + display: none; + animation: toastReveal .5s; +} + +.toastWindow .toastText { + color: rgb(0, 0, 0); + font-family: 'Roboto', sans-serif; + font-size: 20px; + width: 80%; + position: absolute; + top: 28%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; +} + +/*Toast Animation*/ + +@keyframes toastReveal { + 0% { + bottom: -180px; + } + 100% { + bottom: 30px; + } +} + +/*Debug Panel Animations*/ + +@keyframes debugPanelActive { + 0% { + transform: translate(-50%, 50%); + } + 100% { + transform: translate(-50%, -50%); + } +} + +@keyframes debugPanelInactive { + 0% { + transform: translate(-50%, -50%); + } + 100% { + transform: translate(-50%, 50%); + } +} + +@keyframes countdownTimer { + 0% { + left: 50%; + } + 100% { + left: -50%; + } +} \ No newline at end of file diff --git a/public/css/schedule.css b/public/css/schedule.css new file mode 100644 index 0000000..3bdad60 --- /dev/null +++ b/public/css/schedule.css @@ -0,0 +1,123 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap'); + .gamestatus { + color: white; + font-family: 'Roboto', sans-serif; + font-size: 30px; + width: 90%; + position: absolute; + top: 28%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; +} + .nextgame { + color: white; + font-family: 'Roboto', sans-serif; + font-size: 10pt; + width: 100%; + position: absolute; + top: 25%; + left: 50%; + transform: translate(-50%, 0px); + text-align: center; +} + .logo { + width: 40%; + display: block; + margin: auto; + margin-top: 10%; +} + .center { + height: 100vh; + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + body { + aspect-ratio: 1/1; + background-color: #000000; + animation-name: bg_animation; + animation-duration: 15s; + animation-timing-function: linear; + animation-delay: 0; + animation-iteration-count: infinite; + animation-direction: alternate; + animation-play-state: running; +} + .startbtn { + background-color: rgba(255, 255, 255, 0.3); + position: absolute; + width: 90%; + bottom: 0px; + left: 50%; + transform: translate(-50%, 0px); + margin-right: 20px; + border-radius: 50px; + margin-bottom: 20px; + color: white; + padding: 20px 0px 20px 0px; + text-align: center; + font-size: 15pt; + font-family: 'Roboto', sans-serif; + display: block; +} + .profilecard { + left: 50%; + height: 45%; + bottom: 100px; + border-radius: 20px; + transform: translate(-50%, 0); + background: white; + width: 90%; + position: absolute; +} + +.joingame { + background-color: rgb(255, 0, 119); + position: absolute; + width: 50%; + bottom: 440px; + left: 50%; + transform: translate(-50%, 0px); + margin-right: 20px; + border-radius: 50px; + margin-bottom: 20px; + color: white; + padding: 20px 0px 20px 0px; + text-align: center; + font-size: 15pt; + font-family: 'Roboto', sans-serif; + display: block; +} + +/*Live Game Styles*/ + + @keyframes bg_animation { + 0% { + background-color: hsl(157, 52%, 58%); + /* green */ + } + 20% { + background-color: hsl(182, 52%, 57%); + /* light blue */ + } + 40% { + background-color: hsl(225, 46%, 60%); + /* blue */ + } + 60% { + background-color: hsl(280, 45%, 58%); + /* purple */ + } + 80% { + background-color: hsl(323, 40%, 54%); + /* pink */ + } + 100% { + background-color: hsl(32, 52%, 54%); + /* orange */ + } +} diff --git a/public/js/.DS_Store b/public/js/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a2a7e0ef9e8561424bf2d74fac6f8e2a8965d33a GIT binary patch literal 6148 zcmeHK!A{#i5SsXeGE=;)>Kz(yCQ2Zbq8XDXZWFB zIPnEsIC103M=-OysX$JpUZ~n?Mw)%IvopKiXKU930HTuz+W<`fkf?;U6>Js=jgwZS zWkCl&OKm2hVrCF55=)C1Iz$3@Kg-gvqr8y)dD;(Gr$b|vkcJr;Ghz^7E6Qr=)gvo0El&TYeAc8 z3CeLSx)w`=ID#TfDxyghw!{!79sQ1tb1jwzO*#l$d 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') { + 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; + }; + 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; + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + 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) { + 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; + } + }, {}], + 3: [function(_dereq_, module, exports) { + var process = module.exports = {}; + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + + function defaultClearTimeout() { + throw new Error('clearTimeout has not been defined'); + } + (function() { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + }()) + + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + return setTimeout(fun, 0); + } + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + return cachedSetTimeout(fun, 0); + } catch (e) { + try { + return cachedSetTimeout.call(null, fun, 0); + } catch (e) { + return cachedSetTimeout.call(this, fun, 0); + } + } + } + + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + return clearTimeout(marker); + } + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + return cachedClearTimeout(marker); + } catch (e) { + try { + return cachedClearTimeout.call(null, marker); + } catch (e) { + return cachedClearTimeout.call(this, marker); + } + } + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + var len = queue.length; + while (len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + process.nextTick = function(fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function() { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; + process.versions = {}; + + function noop() {} + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + process.prependListener = noop; + process.prependOnceListener = noop; + process.listeners = function(name) { + return [] + } + process.binding = function(name) { + throw new Error('process.binding is not supported'); + }; + process.cwd = function() { + return '/' + }; + process.chdir = function(dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { + return 0; + }; + }, {}], + 4: [function(_dereq_, module, exports) { + var bundleFn = arguments[3]; + var sources = arguments[4]; + var cache = arguments[5]; + var stringify = JSON.stringify; + module.exports = function(fn, options) { + var wkey; + var cacheKeys = Object.keys(cache); + for (var i = 0, l = cacheKeys.length; i < l; i++) { + var key = cacheKeys[i]; + var exp = cache[key].exports; + if (exp === fn || exp && exp.default === fn) { + wkey = key; + break; + } + } + if (!wkey) { + wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); + var wcache = {}; + for (var i = 0, l = cacheKeys.length; i < l; i++) { + var key = cacheKeys[i]; + wcache[key] = key; + } + sources[wkey] = ['function(require,module,exports){' + fn + '(self); }', wcache]; + } + var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); + var scache = {}; + scache[wkey] = wkey; + sources[skey] = ['function(require,module,exports){' + + 'var f = require(' + stringify(wkey) + ');' + + '(f.default ? f.default : f)(self);' + + '}', scache + ]; + var workerSources = {}; + resolveSources(skey); + + function resolveSources(key) { + workerSources[key] = true; + for (var depPath in sources[key][1]) { + var depKey = sources[key][1][depPath]; + if (!workerSources[depKey]) { + resolveSources(depKey); + } + } + } + var src = '(' + bundleFn + ')({' + + Object.keys(workerSources).map(function(key) { + return stringify(key) + ':[' + + sources[key][0] + + ',' + stringify(sources[key][1]) + ']'; + }).join(',') + + '},{},[' + stringify(skey) + '])'; + var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; + var blob = new Blob([src], { + type: 'text/javascript' + }); + if (options && options.bare) { + return blob; + } + var workerUrl = URL.createObjectURL(blob); + var worker = new Worker(workerUrl); + worker.objectURL = workerUrl; + return worker; + }; + }, {}], + 5: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.createDefaultConfig = createDefaultConfig; + var defaultConfig = exports.defaultConfig = { + enableWorker: false, + enableStashBuffer: true, + stashInitialSize: undefined, + isLive: false, + lazyLoad: true, + lazyLoadMaxDuration: 3 * 60, + lazyLoadRecoverDuration: 30, + deferLoadAfterSourceOpen: true, + autoCleanupMaxBackwardDuration: 3 * 60, + autoCleanupMinBackwardDuration: 2 * 60, + statisticsInfoReportInterval: 600, + fixAudioTimestampGap: true, + accurateSeek: false, + seekType: 'range', + seekParamStart: 'bstart', + seekParamEnd: 'bend', + rangeLoadZeroStart: false, + customSeekHandler: undefined, + reuseRedirectedURL: false, + headers: undefined, + customLoader: undefined + }; + + function createDefaultConfig() { + return Object.assign({}, defaultConfig); + } + }, {}], + 6: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _ioController = _dereq_('../io/io-controller.js'); + var _ioController2 = _interopRequireDefault(_ioController); + var _config = _dereq_('../config.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var Features = function() { + function Features() { + _classCallCheck(this, Features); + } + _createClass(Features, null, [{ + key: 'supportMSEH264Playback', + value: function supportMSEH264Playback() { + return window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'); + } + }, { + key: 'supportNetworkStreamIO', + value: function supportNetworkStreamIO() { + var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)()); + var loaderType = ioctl.loaderType; + ioctl.destroy(); + return loaderType == 'fetch-stream-loader' || loaderType == 'xhr-moz-chunked-loader'; + } + }, { + key: 'getNetworkLoaderTypeName', + value: function getNetworkLoaderTypeName() { + var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)()); + var loaderType = ioctl.loaderType; + ioctl.destroy(); + return loaderType; + } + }, { + key: 'supportNativeMediaPlayback', + value: function supportNativeMediaPlayback(mimeType) { + if (Features.videoElement == undefined) { + Features.videoElement = window.document.createElement('video'); + } + var canPlay = Features.videoElement.canPlayType(mimeType); + return canPlay === 'probably' || canPlay == 'maybe'; + } + }, { + key: 'getFeatureList', + value: function getFeatureList() { + var features = { + mseFlvPlayback: false, + mseLiveFlvPlayback: false, + networkStreamIO: false, + networkLoaderName: '', + nativeMP4H264Playback: false, + nativeWebmVP8Playback: false, + nativeWebmVP9Playback: false + }; + features.mseFlvPlayback = Features.supportMSEH264Playback(); + features.networkStreamIO = Features.supportNetworkStreamIO(); + features.networkLoaderName = Features.getNetworkLoaderTypeName(); + features.mseLiveFlvPlayback = features.mseFlvPlayback && features.networkStreamIO; + features.nativeMP4H264Playback = Features.supportNativeMediaPlayback('video/mp4; codecs="avc1.42001E, mp4a.40.2"'); + features.nativeWebmVP8Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp8.0, vorbis"'); + features.nativeWebmVP9Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp9"'); + return features; + } + }]); + return Features; + }(); + exports.default = Features; + }, { + "../config.js": 5, + "../io/io-controller.js": 23 + }], + 7: [function(_dereq_, module, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var MediaInfo = function() { + function MediaInfo() { + _classCallCheck(this, MediaInfo); + this.mimeType = null; + this.duration = null; + this.hasAudio = null; + this.hasVideo = null; + this.audioCodec = null; + this.videoCodec = null; + this.audioDataRate = null; + this.videoDataRate = null; + this.audioSampleRate = null; + this.audioChannelCount = null; + this.width = null; + this.height = null; + this.fps = null; + this.profile = null; + this.level = null; + this.refFrames = null; + this.chromaFormat = null; + this.sarNum = null; + this.sarDen = null; + this.metadata = null; + this.segments = null; + this.segmentCount = null; + this.hasKeyframesIndex = null; + this.keyframesIndex = null; + } + _createClass(MediaInfo, [{ + key: "isComplete", + value: function isComplete() { + var audioInfoComplete = this.hasAudio === false || this.hasAudio === true && this.audioCodec != null && this.audioSampleRate != null && this.audioChannelCount != null; + var videoInfoComplete = this.hasVideo === false || this.hasVideo === true && this.videoCodec != null && this.width != null && this.height != null && this.fps != null && this.profile != null && this.level != null && this.refFrames != null && this.chromaFormat != null && this.sarNum != null && this.sarDen != null; + return this.mimeType != null && this.duration != null && this.metadata != null && this.hasKeyframesIndex != null && audioInfoComplete && videoInfoComplete; + } + }, { + key: "isSeekable", + value: function isSeekable() { + return this.hasKeyframesIndex === true; + } + }, { + key: "getNearestKeyframe", + value: function getNearestKeyframe(milliseconds) { + if (this.keyframesIndex == null) { + return null; + } + var table = this.keyframesIndex; + var keyframeIdx = this._search(table.times, milliseconds); + return { + index: keyframeIdx, + milliseconds: table.times[keyframeIdx], + fileposition: table.filepositions[keyframeIdx] + }; + } + }, { + key: "_search", + value: function _search(list, value) { + var idx = 0; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (value < list[0]) { + idx = 0; + lbound = ubound + 1; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if (mid === last || value >= list[mid] && value < list[mid + 1]) { + idx = mid; + break; + } else if (list[mid] < value) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return idx; + } + }]); + return MediaInfo; + }(); + exports.default = MediaInfo; + }, {}], + 8: [function(_dereq_, module, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var SampleInfo = exports.SampleInfo = function SampleInfo(dts, pts, duration, originalDts, isSync) { + _classCallCheck(this, SampleInfo); + this.dts = dts; + this.pts = pts; + this.duration = duration; + this.originalDts = originalDts; + this.isSyncPoint = isSync; + this.fileposition = null; + }; + var MediaSegmentInfo = exports.MediaSegmentInfo = function() { + function MediaSegmentInfo() { + _classCallCheck(this, MediaSegmentInfo); + this.beginDts = 0; + this.endDts = 0; + this.beginPts = 0; + this.endPts = 0; + this.originalBeginDts = 0; + this.originalEndDts = 0; + this.syncPoints = []; + this.firstSample = null; + this.lastSample = null; + } + _createClass(MediaSegmentInfo, [{ + key: "appendSyncPoint", + value: function appendSyncPoint(sampleInfo) { + sampleInfo.isSyncPoint = true; + this.syncPoints.push(sampleInfo); + } + }]); + return MediaSegmentInfo; + }(); + var IDRSampleList = exports.IDRSampleList = function() { + function IDRSampleList() { + _classCallCheck(this, IDRSampleList); + this._list = []; + } + _createClass(IDRSampleList, [{ + key: "clear", + value: function clear() { + this._list = []; + } + }, { + key: "appendArray", + value: function appendArray(syncPoints) { + var list = this._list; + if (syncPoints.length === 0) { + return; + } + if (list.length > 0 && syncPoints[0].originalDts < list[list.length - 1].originalDts) { + this.clear(); + } + Array.prototype.push.apply(list, syncPoints); + } + }, { + key: "getLastSyncPointBeforeDts", + value: function getLastSyncPointBeforeDts(dts) { + if (this._list.length == 0) { + return null; + } + var list = this._list; + var idx = 0; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (dts < list[0].dts) { + idx = 0; + lbound = ubound + 1; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if (mid === last || dts >= list[mid].dts && dts < list[mid + 1].dts) { + idx = mid; + break; + } else if (list[mid].dts < dts) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return this._list[idx]; + } + }]); + return IDRSampleList; + }(); + var MediaSegmentInfoList = exports.MediaSegmentInfoList = function() { + function MediaSegmentInfoList(type) { + _classCallCheck(this, MediaSegmentInfoList); + this._type = type; + this._list = []; + this._lastAppendLocation = -1; + } + _createClass(MediaSegmentInfoList, [{ + key: "isEmpty", + value: function isEmpty() { + return this._list.length === 0; + } + }, { + key: "clear", + value: function clear() { + this._list = []; + this._lastAppendLocation = -1; + } + }, { + key: "_searchNearestSegmentBefore", + value: function _searchNearestSegmentBefore(originalBeginDts) { + var list = this._list; + if (list.length === 0) { + return -2; + } + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + var idx = 0; + if (originalBeginDts < list[0].originalBeginDts) { + idx = -1; + return idx; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if (mid === last || originalBeginDts > list[mid].lastSample.originalDts && originalBeginDts < list[mid + 1].originalBeginDts) { + idx = mid; + break; + } else if (list[mid].originalBeginDts < originalBeginDts) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return idx; + } + }, { + key: "_searchNearestSegmentAfter", + value: function _searchNearestSegmentAfter(originalBeginDts) { + return this._searchNearestSegmentBefore(originalBeginDts) + 1; + } + }, { + key: "append", + value: function append(mediaSegmentInfo) { + var list = this._list; + var msi = mediaSegmentInfo; + var lastAppendIdx = this._lastAppendLocation; + var insertIdx = 0; + if (lastAppendIdx !== -1 && lastAppendIdx < list.length && msi.originalBeginDts >= list[lastAppendIdx].lastSample.originalDts && (lastAppendIdx === list.length - 1 || lastAppendIdx < list.length - 1 && msi.originalBeginDts < list[lastAppendIdx + 1].originalBeginDts)) { + insertIdx = lastAppendIdx + 1; + } else { + if (list.length > 0) { + insertIdx = this._searchNearestSegmentBefore(msi.originalBeginDts) + 1; + } + } + this._lastAppendLocation = insertIdx; + this._list.splice(insertIdx, 0, msi); + } + }, { + key: "getLastSegmentBefore", + value: function getLastSegmentBefore(originalBeginDts) { + var idx = this._searchNearestSegmentBefore(originalBeginDts); + if (idx >= 0) { + return this._list[idx]; + } else { + return null; + } + } + }, { + key: "getLastSampleBefore", + value: function getLastSampleBefore(originalBeginDts) { + var segment = this.getLastSegmentBefore(originalBeginDts); + if (segment != null) { + return segment.lastSample; + } else { + return null; + } + } + }, { + key: "getLastSyncPointBefore", + value: function getLastSyncPointBefore(originalBeginDts) { + var segmentIdx = this._searchNearestSegmentBefore(originalBeginDts); + var syncPoints = this._list[segmentIdx].syncPoints; + while (syncPoints.length === 0 && segmentIdx > 0) { + segmentIdx--; + syncPoints = this._list[segmentIdx].syncPoints; + } + if (syncPoints.length > 0) { + return syncPoints[syncPoints.length - 1]; + } else { + return null; + } + } + }, { + key: "type", + get: function get() { + return this._type; + } + }, { + key: "length", + get: function get() { + return this._list.length; + } + }]); + return MediaSegmentInfoList; + }(); + }, {}], + 9: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _browser = _dereq_('../utils/browser.js'); + var _browser2 = _interopRequireDefault(_browser); + var _mseEvents = _dereq_('./mse-events.js'); + var _mseEvents2 = _interopRequireDefault(_mseEvents); + var _mediaSegmentInfo = _dereq_('./media-segment-info.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var MSEController = function() { + function MSEController(config) { + _classCallCheck(this, MSEController); + this.TAG = 'MSEController'; + this._config = config; + this._emitter = new _events2.default(); + if (this._config.isLive && this._config.autoCleanupSourceBuffer == undefined) { + this._config.autoCleanupSourceBuffer = true; + } + this.e = { + onSourceOpen: this._onSourceOpen.bind(this), + onSourceEnded: this._onSourceEnded.bind(this), + onSourceClose: this._onSourceClose.bind(this), + onSourceBufferError: this._onSourceBufferError.bind(this), + onSourceBufferUpdateEnd: this._onSourceBufferUpdateEnd.bind(this) + }; + this._mediaSource = null; + this._mediaSourceObjectURL = null; + this._mediaElement = null; + this._isBufferFull = false; + this._hasPendingEos = false; + this._requireSetMediaDuration = false; + this._pendingMediaDuration = 0; + this._pendingSourceBufferInit = []; + this._mimeTypes = { + video: null, + audio: null + }; + this._sourceBuffers = { + video: null, + audio: null + }; + this._lastInitSegments = { + video: null, + audio: null + }; + this._pendingSegments = { + video: [], + audio: [] + }; + this._pendingRemoveRanges = { + video: [], + audio: [] + }; + this._idrList = new _mediaSegmentInfo.IDRSampleList(); + } + _createClass(MSEController, [{ + key: 'destroy', + value: function destroy() { + if (this._mediaElement || this._mediaSource) { + this.detachMediaElement(); + } + this.e = null; + this._emitter.removeAllListeners(); + this._emitter = null; + } + }, { + key: 'on', + value: function on(event, listener) { + this._emitter.addListener(event, listener); + } + }, { + key: 'off', + value: function off(event, listener) { + this._emitter.removeListener(event, listener); + } + }, { + key: 'attachMediaElement', + value: function attachMediaElement(mediaElement) { + if (this._mediaSource) { + throw new _exception.IllegalStateException('MediaSource has been attached to an HTMLMediaElement!'); + } + var ms = this._mediaSource = new window.MediaSource(); + ms.addEventListener('sourceopen', this.e.onSourceOpen); + ms.addEventListener('sourceended', this.e.onSourceEnded); + ms.addEventListener('sourceclose', this.e.onSourceClose); + this._mediaElement = mediaElement; + this._mediaSourceObjectURL = window.URL.createObjectURL(this._mediaSource); + mediaElement.src = this._mediaSourceObjectURL; + } + }, { + key: 'detachMediaElement', + value: function detachMediaElement() { + if (this._mediaSource) { + var ms = this._mediaSource; + for (var type in this._sourceBuffers) { + var ps = this._pendingSegments[type]; + ps.splice(0, ps.length); + this._pendingSegments[type] = null; + this._pendingRemoveRanges[type] = null; + this._lastInitSegments[type] = null; + var sb = this._sourceBuffers[type]; + if (sb) { + if (ms.readyState !== 'closed') { + try { + ms.removeSourceBuffer(sb); + } catch (error) { + _logger2.default.e(this.TAG, error.message); + } + sb.removeEventListener('error', this.e.onSourceBufferError); + sb.removeEventListener('updateend', this.e.onSourceBufferUpdateEnd); + } + this._mimeTypes[type] = null; + this._sourceBuffers[type] = null; + } + } + if (ms.readyState === 'open') { + try { + ms.endOfStream(); + } catch (error) { + _logger2.default.e(this.TAG, error.message); + } + } + ms.removeEventListener('sourceopen', this.e.onSourceOpen); + ms.removeEventListener('sourceended', this.e.onSourceEnded); + ms.removeEventListener('sourceclose', this.e.onSourceClose); + this._pendingSourceBufferInit = []; + this._isBufferFull = false; + this._idrList.clear(); + this._mediaSource = null; + } + if (this._mediaElement) { + this._mediaElement.src = ''; + this._mediaElement.removeAttribute('src'); + this._mediaElement = null; + } + if (this._mediaSourceObjectURL) { + window.URL.revokeObjectURL(this._mediaSourceObjectURL); + this._mediaSourceObjectURL = null; + } + } + }, { + key: 'appendInitSegment', + value: function appendInitSegment(initSegment, deferred) { + if (!this._mediaSource || this._mediaSource.readyState !== 'open') { + this._pendingSourceBufferInit.push(initSegment); + this._pendingSegments[initSegment.type].push(initSegment); + return; + } + var is = initSegment; + var mimeType = '' + is.container; + if (is.codec && is.codec.length > 0) { + mimeType += ';codecs=' + is.codec; + } + var firstInitSegment = false; + _logger2.default.v(this.TAG, 'Received Initialization Segment, mimeType: ' + mimeType); + this._lastInitSegments[is.type] = is; + if (mimeType !== this._mimeTypes[is.type]) { + if (!this._mimeTypes[is.type]) { + firstInitSegment = true; + try { + var sb = this._sourceBuffers[is.type] = this._mediaSource.addSourceBuffer(mimeType); + sb.addEventListener('error', this.e.onSourceBufferError); + sb.addEventListener('updateend', this.e.onSourceBufferUpdateEnd); + } catch (error) { + _logger2.default.e(this.TAG, error.message); + this._emitter.emit(_mseEvents2.default.ERROR, { + code: error.code, + msg: error.message + }); + return; + } + } else { + _logger2.default.v(this.TAG, 'Notice: ' + is.type + ' mimeType changed, origin: ' + this._mimeTypes[is.type] + ', target: ' + mimeType); + } + this._mimeTypes[is.type] = mimeType; + } + if (!deferred) { + this._pendingSegments[is.type].push(is); + } + if (!firstInitSegment) { + if (this._sourceBuffers[is.type] && !this._sourceBuffers[is.type].updating) { + this._doAppendSegments(); + } + } + if (_browser2.default.safari && is.container === 'audio/mpeg' && is.mediaDuration > 0) { + this._requireSetMediaDuration = true; + this._pendingMediaDuration = is.mediaDuration / 1000; + this._updateMediaSourceDuration(); + } + } + }, { + key: 'appendMediaSegment', + value: function appendMediaSegment(mediaSegment) { + var ms = mediaSegment; + this._pendingSegments[ms.type].push(ms); + if (this._config.autoCleanupSourceBuffer && this._needCleanupSourceBuffer()) { + this._doCleanupSourceBuffer(); + } + var sb = this._sourceBuffers[ms.type]; + if (sb && !sb.updating && !this._hasPendingRemoveRanges()) { + this._doAppendSegments(); + } + } + }, { + key: 'seek', + value: function seek(seconds) { + for (var type in this._sourceBuffers) { + if (!this._sourceBuffers[type]) { + continue; + } + var sb = this._sourceBuffers[type]; + if (this._mediaSource.readyState === 'open') { + try { + sb.abort(); + } catch (error) { + _logger2.default.e(this.TAG, error.message); + } + } + this._idrList.clear(); + var ps = this._pendingSegments[type]; + ps.splice(0, ps.length); + if (this._mediaSource.readyState === 'closed') { + continue; + } + for (var i = 0; i < sb.buffered.length; i++) { + var start = sb.buffered.start(i); + var end = sb.buffered.end(i); + this._pendingRemoveRanges[type].push({ + start: start, + end: end + }); + } + if (!sb.updating) { + this._doRemoveRanges(); + } + if (_browser2.default.safari) { + var lastInitSegment = this._lastInitSegments[type]; + if (lastInitSegment) { + this._pendingSegments[type].push(lastInitSegment); + if (!sb.updating) { + this._doAppendSegments(); + } + } + } + } + } + }, { + key: 'endOfStream', + value: function endOfStream() { + var ms = this._mediaSource; + var sb = this._sourceBuffers; + if (!ms || ms.readyState !== 'open') { + if (ms && ms.readyState === 'closed' && this._hasPendingSegments()) { + this._hasPendingEos = true; + } + return; + } + if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) { + this._hasPendingEos = true; + } else { + this._hasPendingEos = false; + ms.endOfStream(); + } + } + }, { + key: 'getNearestKeyframe', + value: function getNearestKeyframe(dts) { + return this._idrList.getLastSyncPointBeforeDts(dts); + } + }, { + key: '_needCleanupSourceBuffer', + value: function _needCleanupSourceBuffer() { + if (!this._config.autoCleanupSourceBuffer) { + return false; + } + var currentTime = this._mediaElement.currentTime; + for (var type in this._sourceBuffers) { + var sb = this._sourceBuffers[type]; + if (sb) { + var buffered = sb.buffered; + if (buffered.length >= 1) { + if (currentTime - buffered.start(0) >= this._config.autoCleanupMaxBackwardDuration) { + return true; + } + } + } + } + return false; + } + }, { + key: '_doCleanupSourceBuffer', + value: function _doCleanupSourceBuffer() { + var currentTime = this._mediaElement.currentTime; + for (var type in this._sourceBuffers) { + var sb = this._sourceBuffers[type]; + if (sb) { + var buffered = sb.buffered; + var doRemove = false; + for (var i = 0; i < buffered.length; i++) { + var start = buffered.start(i); + var end = buffered.end(i); + if (start <= currentTime && currentTime < end + 3) { + if (currentTime - start >= this._config.autoCleanupMaxBackwardDuration) { + doRemove = true; + var removeEnd = currentTime - this._config.autoCleanupMinBackwardDuration; + this._pendingRemoveRanges[type].push({ + start: start, + end: removeEnd + }); + } + } else if (end < currentTime) { + doRemove = true; + this._pendingRemoveRanges[type].push({ + start: start, + end: end + }); + } + } + if (doRemove && !sb.updating) { + this._doRemoveRanges(); + } + } + } + } + }, { + key: '_updateMediaSourceDuration', + value: function _updateMediaSourceDuration() { + var sb = this._sourceBuffers; + if (this._mediaElement.readyState === 0 || this._mediaSource.readyState !== 'open') { + return; + } + if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) { + return; + } + var current = this._mediaSource.duration; + var target = this._pendingMediaDuration; + if (target > 0 && (isNaN(current) || target > current)) { + _logger2.default.v(this.TAG, 'Update MediaSource duration from ' + current + ' to ' + target); + this._mediaSource.duration = target; + } + this._requireSetMediaDuration = false; + this._pendingMediaDuration = 0; + } + }, { + key: '_doRemoveRanges', + value: function _doRemoveRanges() { + for (var type in this._pendingRemoveRanges) { + if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) { + continue; + } + var sb = this._sourceBuffers[type]; + var ranges = this._pendingRemoveRanges[type]; + while (ranges.length && !sb.updating) { + var range = ranges.shift(); + sb.remove(range.start, range.end); + } + } + } + }, { + key: '_doAppendSegments', + value: function _doAppendSegments() { + var pendingSegments = this._pendingSegments; + for (var type in pendingSegments) { + if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) { + continue; + } + if (pendingSegments[type].length > 0) { + var segment = pendingSegments[type].shift(); + if (segment.timestampOffset) { + var currentOffset = this._sourceBuffers[type].timestampOffset; + var targetOffset = segment.timestampOffset / 1000; + var delta = Math.abs(currentOffset - targetOffset); + if (delta > 0.1) { + _logger2.default.v(this.TAG, 'Update MPEG audio timestampOffset from ' + currentOffset + ' to ' + targetOffset); + this._sourceBuffers[type].timestampOffset = targetOffset; + } + delete segment.timestampOffset; + } + if (!segment.data || segment.data.byteLength === 0) { + continue; + } + try { + this._sourceBuffers[type].appendBuffer(segment.data); + this._isBufferFull = false; + if (type === 'video' && segment.hasOwnProperty('info')) { + this._idrList.appendArray(segment.info.syncPoints); + } + } catch (error) { + this._pendingSegments[type].unshift(segment); + if (error.code === 22) { + if (!this._isBufferFull) { + this._emitter.emit(_mseEvents2.default.BUFFER_FULL); + } + this._isBufferFull = true; + } else { + _logger2.default.e(this.TAG, error.message); + this._emitter.emit(_mseEvents2.default.ERROR, { + code: error.code, + msg: error.message + }); + } + } + } + } + } + }, { + key: '_onSourceOpen', + value: function _onSourceOpen() { + _logger2.default.v(this.TAG, 'MediaSource onSourceOpen'); + this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen); + if (this._pendingSourceBufferInit.length > 0) { + var pendings = this._pendingSourceBufferInit; + while (pendings.length) { + var segment = pendings.shift(); + this.appendInitSegment(segment, true); + } + } + if (this._hasPendingSegments()) { + this._doAppendSegments(); + } + this._emitter.emit(_mseEvents2.default.SOURCE_OPEN); + } + }, { + key: '_onSourceEnded', + value: function _onSourceEnded() { + _logger2.default.v(this.TAG, 'MediaSource onSourceEnded'); + } + }, { + key: '_onSourceClose', + value: function _onSourceClose() { + _logger2.default.v(this.TAG, 'MediaSource onSourceClose'); + if (this._mediaSource && this.e != null) { + this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen); + this._mediaSource.removeEventListener('sourceended', this.e.onSourceEnded); + this._mediaSource.removeEventListener('sourceclose', this.e.onSourceClose); + } + } + }, { + key: '_hasPendingSegments', + value: function _hasPendingSegments() { + var ps = this._pendingSegments; + return ps.video.length > 0 || ps.audio.length > 0; + } + }, { + key: '_hasPendingRemoveRanges', + value: function _hasPendingRemoveRanges() { + var prr = this._pendingRemoveRanges; + return prr.video.length > 0 || prr.audio.length > 0; + } + }, { + key: '_onSourceBufferUpdateEnd', + value: function _onSourceBufferUpdateEnd() { + if (this._requireSetMediaDuration) { + this._updateMediaSourceDuration(); + } else if (this._hasPendingRemoveRanges()) { + this._doRemoveRanges(); + } else if (this._hasPendingSegments()) { + this._doAppendSegments(); + } else if (this._hasPendingEos) { + this.endOfStream(); + } + this._emitter.emit(_mseEvents2.default.UPDATE_END); + } + }, { + key: '_onSourceBufferError', + value: function _onSourceBufferError(e) { + _logger2.default.e(this.TAG, 'SourceBuffer Error: ' + e); + } + }]); + return MSEController; + }(); + exports.default = MSEController; + }, { + "../utils/browser.js": 39, + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./media-segment-info.js": 8, + "./mse-events.js": 10, + "events": 2 + }], + 10: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var MSEEvents = { + ERROR: 'error', + SOURCE_OPEN: 'source_open', + UPDATE_END: 'update_end', + BUFFER_FULL: 'buffer_full' + }; + exports.default = MSEEvents; + }, {}], + 11: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _loggingControl = _dereq_('../utils/logging-control.js'); + var _loggingControl2 = _interopRequireDefault(_loggingControl); + var _transmuxingController = _dereq_('./transmuxing-controller.js'); + var _transmuxingController2 = _interopRequireDefault(_transmuxingController); + var _transmuxingEvents = _dereq_('./transmuxing-events.js'); + var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); + var _transmuxingWorker = _dereq_('./transmuxing-worker.js'); + var _transmuxingWorker2 = _interopRequireDefault(_transmuxingWorker); + var _mediaInfo = _dereq_('./media-info.js'); + var _mediaInfo2 = _interopRequireDefault(_mediaInfo); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var Transmuxer = function() { + function Transmuxer(mediaDataSource, config) { + _classCallCheck(this, Transmuxer); + this.TAG = 'Transmuxer'; + this._emitter = new _events2.default(); + if (config.enableWorker && typeof Worker !== 'undefined') { + try { + var work = _dereq_('webworkify'); + this._worker = work(_transmuxingWorker2.default); + this._workerDestroying = false; + this._worker.addEventListener('message', this._onWorkerMessage.bind(this)); + this._worker.postMessage({ + cmd: 'init', + param: [mediaDataSource, config] + }); + this.e = { + onLoggingConfigChanged: this._onLoggingConfigChanged.bind(this) + }; + _loggingControl2.default.registerListener(this.e.onLoggingConfigChanged); + this._worker.postMessage({ + cmd: 'logging_config', + param: _loggingControl2.default.getConfig() + }); + } catch (error) { + _logger2.default.e(this.TAG, 'Error while initialize transmuxing worker, fallback to inline transmuxing'); + this._worker = null; + this._controller = new _transmuxingController2.default(mediaDataSource, config); + } + } else { + this._controller = new _transmuxingController2.default(mediaDataSource, config); + } + if (this._controller) { + var ctl = this._controller; + ctl.on(_transmuxingEvents2.default.IO_ERROR, this._onIOError.bind(this)); + ctl.on(_transmuxingEvents2.default.DEMUX_ERROR, this._onDemuxError.bind(this)); + ctl.on(_transmuxingEvents2.default.INIT_SEGMENT, this._onInitSegment.bind(this)); + ctl.on(_transmuxingEvents2.default.MEDIA_SEGMENT, this._onMediaSegment.bind(this)); + ctl.on(_transmuxingEvents2.default.LOADING_COMPLETE, this._onLoadingComplete.bind(this)); + ctl.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, this._onRecoveredEarlyEof.bind(this)); + ctl.on(_transmuxingEvents2.default.MEDIA_INFO, this._onMediaInfo.bind(this)); + ctl.on(_transmuxingEvents2.default.METADATA_ARRIVED, this._onMetaDataArrived.bind(this)); + ctl.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, this._onScriptDataArrived.bind(this)); + ctl.on(_transmuxingEvents2.default.STATISTICS_INFO, this._onStatisticsInfo.bind(this)); + ctl.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, this._onRecommendSeekpoint.bind(this)); + } + } + _createClass(Transmuxer, [{ + key: 'destroy', + value: function destroy() { + if (this._worker) { + if (!this._workerDestroying) { + this._workerDestroying = true; + this._worker.postMessage({ + cmd: 'destroy' + }); + _loggingControl2.default.removeListener(this.e.onLoggingConfigChanged); + this.e = null; + } + } else { + this._controller.destroy(); + this._controller = null; + } + this._emitter.removeAllListeners(); + this._emitter = null; + } + }, { + key: 'on', + value: function on(event, listener) { + this._emitter.addListener(event, listener); + } + }, { + key: 'off', + value: function off(event, listener) { + this._emitter.removeListener(event, listener); + } + }, { + key: 'hasWorker', + value: function hasWorker() { + return this._worker != null; + } + }, { + key: 'open', + value: function open() { + if (this._worker) { + this._worker.postMessage({ + cmd: 'start' + }); + } else { + this._controller.start(); + } + } + }, { + key: 'close', + value: function close() { + if (this._worker) { + this._worker.postMessage({ + cmd: 'stop' + }); + } else { + this._controller.stop(); + } + } + }, { + key: 'seek', + value: function seek(milliseconds) { + if (this._worker) { + this._worker.postMessage({ + cmd: 'seek', + param: milliseconds + }); + } else { + this._controller.seek(milliseconds); + } + } + }, { + key: 'pause', + value: function pause() { + if (this._worker) { + this._worker.postMessage({ + cmd: 'pause' + }); + } else { + this._controller.pause(); + } + } + }, { + key: 'resume', + value: function resume() { + if (this._worker) { + this._worker.postMessage({ + cmd: 'resume' + }); + } else { + this._controller.resume(); + } + } + }, { + key: '_onInitSegment', + value: function _onInitSegment(type, initSegment) { + var _this = this; + Promise.resolve().then(function() { + _this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment); + }); + } + }, { + key: '_onMediaSegment', + value: function _onMediaSegment(type, mediaSegment) { + var _this2 = this; + Promise.resolve().then(function() { + _this2._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment); + }); + } + }, { + key: '_onLoadingComplete', + value: function _onLoadingComplete() { + var _this3 = this; + Promise.resolve().then(function() { + _this3._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE); + }); + } + }, { + key: '_onRecoveredEarlyEof', + value: function _onRecoveredEarlyEof() { + var _this4 = this; + Promise.resolve().then(function() { + _this4._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF); + }); + } + }, { + key: '_onMediaInfo', + value: function _onMediaInfo(mediaInfo) { + var _this5 = this; + Promise.resolve().then(function() { + _this5._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, mediaInfo); + }); + } + }, { + key: '_onMetaDataArrived', + value: function _onMetaDataArrived(metadata) { + var _this6 = this; + Promise.resolve().then(function() { + _this6._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata); + }); + } + }, { + key: '_onScriptDataArrived', + value: function _onScriptDataArrived(data) { + var _this7 = this; + Promise.resolve().then(function() { + _this7._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data); + }); + } + }, { + key: '_onStatisticsInfo', + value: function _onStatisticsInfo(statisticsInfo) { + var _this8 = this; + Promise.resolve().then(function() { + _this8._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, statisticsInfo); + }); + } + }, { + key: '_onIOError', + value: function _onIOError(type, info) { + var _this9 = this; + Promise.resolve().then(function() { + _this9._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info); + }); + } + }, { + key: '_onDemuxError', + value: function _onDemuxError(type, info) { + var _this10 = this; + Promise.resolve().then(function() { + _this10._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info); + }); + } + }, { + key: '_onRecommendSeekpoint', + value: function _onRecommendSeekpoint(milliseconds) { + var _this11 = this; + Promise.resolve().then(function() { + _this11._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, milliseconds); + }); + } + }, { + key: '_onLoggingConfigChanged', + value: function _onLoggingConfigChanged(config) { + if (this._worker) { + this._worker.postMessage({ + cmd: 'logging_config', + param: config + }); + } + } + }, { + key: '_onWorkerMessage', + value: function _onWorkerMessage(e) { + var message = e.data; + var data = message.data; + if (message.msg === 'destroyed' || this._workerDestroying) { + this._workerDestroying = false; + this._worker.terminate(); + this._worker = null; + return; + } + switch (message.msg) { + case _transmuxingEvents2.default.INIT_SEGMENT: + case _transmuxingEvents2.default.MEDIA_SEGMENT: + this._emitter.emit(message.msg, data.type, data.data); + break; + case _transmuxingEvents2.default.LOADING_COMPLETE: + case _transmuxingEvents2.default.RECOVERED_EARLY_EOF: + this._emitter.emit(message.msg); + break; + case _transmuxingEvents2.default.MEDIA_INFO: + Object.setPrototypeOf(data, _mediaInfo2.default.prototype); + this._emitter.emit(message.msg, data); + break; + case _transmuxingEvents2.default.METADATA_ARRIVED: + case _transmuxingEvents2.default.SCRIPTDATA_ARRIVED: + case _transmuxingEvents2.default.STATISTICS_INFO: + this._emitter.emit(message.msg, data); + break; + case _transmuxingEvents2.default.IO_ERROR: + case _transmuxingEvents2.default.DEMUX_ERROR: + this._emitter.emit(message.msg, data.type, data.info); + break; + case _transmuxingEvents2.default.RECOMMEND_SEEKPOINT: + this._emitter.emit(message.msg, data); + break; + case 'logcat_callback': + _logger2.default.emitter.emit('log', data.type, data.logcat); + break; + default: + break; + } + } + }]); + return Transmuxer; + }(); + exports.default = Transmuxer; + }, { + "../utils/logger.js": 41, + "../utils/logging-control.js": 42, + "./media-info.js": 7, + "./transmuxing-controller.js": 12, + "./transmuxing-events.js": 13, + "./transmuxing-worker.js": 14, + "events": 2, + "webworkify": 4 + }], + 12: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _browser = _dereq_('../utils/browser.js'); + var _browser2 = _interopRequireDefault(_browser); + var _mediaInfo = _dereq_('./media-info.js'); + var _mediaInfo2 = _interopRequireDefault(_mediaInfo); + var _flvDemuxer = _dereq_('../demux/flv-demuxer.js'); + var _flvDemuxer2 = _interopRequireDefault(_flvDemuxer); + var _mp4Remuxer = _dereq_('../remux/mp4-remuxer.js'); + var _mp4Remuxer2 = _interopRequireDefault(_mp4Remuxer); + var _demuxErrors = _dereq_('../demux/demux-errors.js'); + var _demuxErrors2 = _interopRequireDefault(_demuxErrors); + var _ioController = _dereq_('../io/io-controller.js'); + var _ioController2 = _interopRequireDefault(_ioController); + var _transmuxingEvents = _dereq_('./transmuxing-events.js'); + var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); + var _loader = _dereq_('../io/loader.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var TransmuxingController = function() { + function TransmuxingController(mediaDataSource, config) { + _classCallCheck(this, TransmuxingController); + this.TAG = 'TransmuxingController'; + this._emitter = new _events2.default(); + this._config = config; + if (!mediaDataSource.segments) { + mediaDataSource.segments = [{ + duration: mediaDataSource.duration, + filesize: mediaDataSource.filesize, + url: mediaDataSource.url + }]; + } + if (typeof mediaDataSource.cors !== 'boolean') { + mediaDataSource.cors = true; + } + if (typeof mediaDataSource.withCredentials !== 'boolean') { + mediaDataSource.withCredentials = false; + } + this._mediaDataSource = mediaDataSource; + this._currentSegmentIndex = 0; + var totalDuration = 0; + this._mediaDataSource.segments.forEach(function(segment) { + segment.timestampBase = totalDuration; + totalDuration += segment.duration; + segment.cors = mediaDataSource.cors; + segment.withCredentials = mediaDataSource.withCredentials; + if (config.referrerPolicy) { + segment.referrerPolicy = config.referrerPolicy; + } + }); + if (!isNaN(totalDuration) && this._mediaDataSource.duration !== totalDuration) { + this._mediaDataSource.duration = totalDuration; + } + this._mediaInfo = null; + this._demuxer = null; + this._remuxer = null; + this._ioctl = null; + this._pendingSeekTime = null; + this._pendingResolveSeekPoint = null; + this._statisticsReporter = null; + } + _createClass(TransmuxingController, [{ + key: 'destroy', + value: function destroy() { + this._mediaInfo = null; + this._mediaDataSource = null; + if (this._statisticsReporter) { + this._disableStatisticsReporter(); + } + if (this._ioctl) { + this._ioctl.destroy(); + this._ioctl = null; + } + if (this._demuxer) { + this._demuxer.destroy(); + this._demuxer = null; + } + if (this._remuxer) { + this._remuxer.destroy(); + this._remuxer = null; + } + this._emitter.removeAllListeners(); + this._emitter = null; + } + }, { + key: 'on', + value: function on(event, listener) { + this._emitter.addListener(event, listener); + } + }, { + key: 'off', + value: function off(event, listener) { + this._emitter.removeListener(event, listener); + } + }, { + key: 'start', + value: function start() { + this._loadSegment(0); + this._enableStatisticsReporter(); + } + }, { + key: '_loadSegment', + value: function _loadSegment(segmentIndex, optionalFrom) { + this._currentSegmentIndex = segmentIndex; + var dataSource = this._mediaDataSource.segments[segmentIndex]; + var ioctl = this._ioctl = new _ioController2.default(dataSource, this._config, segmentIndex); + ioctl.onError = this._onIOException.bind(this); + ioctl.onSeeked = this._onIOSeeked.bind(this); + ioctl.onComplete = this._onIOComplete.bind(this); + ioctl.onRedirect = this._onIORedirect.bind(this); + ioctl.onRecoveredEarlyEof = this._onIORecoveredEarlyEof.bind(this); + if (optionalFrom) { + this._demuxer.bindDataSource(this._ioctl); + } else { + ioctl.onDataArrival = this._onInitChunkArrival.bind(this); + } + ioctl.open(optionalFrom); + } + }, { + key: 'stop', + value: function stop() { + this._internalAbort(); + this._disableStatisticsReporter(); + } + }, { + key: '_internalAbort', + value: function _internalAbort() { + if (this._ioctl) { + this._ioctl.destroy(); + this._ioctl = null; + } + } + }, { + key: 'pause', + value: function pause() { + if (this._ioctl && this._ioctl.isWorking()) { + this._ioctl.pause(); + this._disableStatisticsReporter(); + } + } + }, { + key: 'resume', + value: function resume() { + if (this._ioctl && this._ioctl.isPaused()) { + this._ioctl.resume(); + this._enableStatisticsReporter(); + } + } + }, { + key: 'seek', + value: function seek(milliseconds) { + if (this._mediaInfo == null || !this._mediaInfo.isSeekable()) { + return; + } + var targetSegmentIndex = this._searchSegmentIndexContains(milliseconds); + if (targetSegmentIndex === this._currentSegmentIndex) { + var segmentInfo = this._mediaInfo.segments[targetSegmentIndex]; + if (segmentInfo == undefined) { + this._pendingSeekTime = milliseconds; + } else { + var keyframe = segmentInfo.getNearestKeyframe(milliseconds); + this._remuxer.seek(keyframe.milliseconds); + this._ioctl.seek(keyframe.fileposition); + this._pendingResolveSeekPoint = keyframe.milliseconds; + } + } else { + var targetSegmentInfo = this._mediaInfo.segments[targetSegmentIndex]; + if (targetSegmentInfo == undefined) { + this._pendingSeekTime = milliseconds; + this._internalAbort(); + this._remuxer.seek(); + this._remuxer.insertDiscontinuity(); + this._loadSegment(targetSegmentIndex); + } else { + var _keyframe = targetSegmentInfo.getNearestKeyframe(milliseconds); + this._internalAbort(); + this._remuxer.seek(milliseconds); + this._remuxer.insertDiscontinuity(); + this._demuxer.resetMediaInfo(); + this._demuxer.timestampBase = this._mediaDataSource.segments[targetSegmentIndex].timestampBase; + this._loadSegment(targetSegmentIndex, _keyframe.fileposition); + this._pendingResolveSeekPoint = _keyframe.milliseconds; + this._reportSegmentMediaInfo(targetSegmentIndex); + } + } + this._enableStatisticsReporter(); + } + }, { + key: '_searchSegmentIndexContains', + value: function _searchSegmentIndexContains(milliseconds) { + var segments = this._mediaDataSource.segments; + var idx = segments.length - 1; + for (var i = 0; i < segments.length; i++) { + if (milliseconds < segments[i].timestampBase) { + idx = i - 1; + break; + } + } + return idx; + } + }, { + key: '_onInitChunkArrival', + value: function _onInitChunkArrival(data, byteStart) { + var _this = this; + var probeData = null; + var consumed = 0; + if (byteStart > 0) { + this._demuxer.bindDataSource(this._ioctl); + this._demuxer.timestampBase = this._mediaDataSource.segments[this._currentSegmentIndex].timestampBase; + consumed = this._demuxer.parseChunks(data, byteStart); + } else if ((probeData = _flvDemuxer2.default.probe(data)).match) { + this._demuxer = new _flvDemuxer2.default(probeData, this._config); + if (!this._remuxer) { + this._remuxer = new _mp4Remuxer2.default(this._config); + } + var mds = this._mediaDataSource; + if (mds.duration != undefined && !isNaN(mds.duration)) { + this._demuxer.overridedDuration = mds.duration; + } + if (typeof mds.hasAudio === 'boolean') { + this._demuxer.overridedHasAudio = mds.hasAudio; + } + if (typeof mds.hasVideo === 'boolean') { + this._demuxer.overridedHasVideo = mds.hasVideo; + } + this._demuxer.timestampBase = mds.segments[this._currentSegmentIndex].timestampBase; + this._demuxer.onError = this._onDemuxException.bind(this); + this._demuxer.onMediaInfo = this._onMediaInfo.bind(this); + this._demuxer.onMetaDataArrived = this._onMetaDataArrived.bind(this); + this._demuxer.onScriptDataArrived = this._onScriptDataArrived.bind(this); + this._remuxer.bindDataSource(this._demuxer.bindDataSource(this._ioctl)); + this._remuxer.onInitSegment = this._onRemuxerInitSegmentArrival.bind(this); + this._remuxer.onMediaSegment = this._onRemuxerMediaSegmentArrival.bind(this); + consumed = this._demuxer.parseChunks(data, byteStart); + } else { + probeData = null; + _logger2.default.e(this.TAG, 'Non-FLV, Unsupported media type!'); + Promise.resolve().then(function() { + _this._internalAbort(); + }); + this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, _demuxErrors2.default.FORMAT_UNSUPPORTED, 'Non-FLV, Unsupported media type'); + consumed = 0; + } + return consumed; + } + }, { + key: '_onMediaInfo', + value: function _onMediaInfo(mediaInfo) { + var _this2 = this; + if (this._mediaInfo == null) { + this._mediaInfo = Object.assign({}, mediaInfo); + this._mediaInfo.keyframesIndex = null; + this._mediaInfo.segments = []; + this._mediaInfo.segmentCount = this._mediaDataSource.segments.length; + Object.setPrototypeOf(this._mediaInfo, _mediaInfo2.default.prototype); + } + var segmentInfo = Object.assign({}, mediaInfo); + Object.setPrototypeOf(segmentInfo, _mediaInfo2.default.prototype); + this._mediaInfo.segments[this._currentSegmentIndex] = segmentInfo; + this._reportSegmentMediaInfo(this._currentSegmentIndex); + if (this._pendingSeekTime != null) { + Promise.resolve().then(function() { + var target = _this2._pendingSeekTime; + _this2._pendingSeekTime = null; + _this2.seek(target); + }); + } + } + }, { + key: '_onMetaDataArrived', + value: function _onMetaDataArrived(metadata) { + this._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata); + } + }, { + key: '_onScriptDataArrived', + value: function _onScriptDataArrived(data) { + this._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data); + } + }, { + key: '_onIOSeeked', + value: function _onIOSeeked() { + this._remuxer.insertDiscontinuity(); + } + }, { + key: '_onIOComplete', + value: function _onIOComplete(extraData) { + var segmentIndex = extraData; + var nextSegmentIndex = segmentIndex + 1; + if (nextSegmentIndex < this._mediaDataSource.segments.length) { + this._internalAbort(); + this._remuxer.flushStashedSamples(); + this._loadSegment(nextSegmentIndex); + } else { + this._remuxer.flushStashedSamples(); + this._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE); + this._disableStatisticsReporter(); + } + } + }, { + key: '_onIORedirect', + value: function _onIORedirect(redirectedURL) { + var segmentIndex = this._ioctl.extraData; + this._mediaDataSource.segments[segmentIndex].redirectedURL = redirectedURL; + } + }, { + key: '_onIORecoveredEarlyEof', + value: function _onIORecoveredEarlyEof() { + this._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF); + } + }, { + key: '_onIOException', + value: function _onIOException(type, info) { + _logger2.default.e(this.TAG, 'IOException: type = ' + type + ', code = ' + info.code + ', msg = ' + info.msg); + this._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info); + this._disableStatisticsReporter(); + } + }, { + key: '_onDemuxException', + value: function _onDemuxException(type, info) { + _logger2.default.e(this.TAG, 'DemuxException: type = ' + type + ', info = ' + info); + this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info); + } + }, { + key: '_onRemuxerInitSegmentArrival', + value: function _onRemuxerInitSegmentArrival(type, initSegment) { + this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment); + } + }, { + key: '_onRemuxerMediaSegmentArrival', + value: function _onRemuxerMediaSegmentArrival(type, mediaSegment) { + if (this._pendingSeekTime != null) { + return; + } + this._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment); + if (this._pendingResolveSeekPoint != null && type === 'video') { + var syncPoints = mediaSegment.info.syncPoints; + var seekpoint = this._pendingResolveSeekPoint; + this._pendingResolveSeekPoint = null; + if (_browser2.default.safari && syncPoints.length > 0 && syncPoints[0].originalDts === seekpoint) { + seekpoint = syncPoints[0].pts; + } + this._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, seekpoint); + } + } + }, { + key: '_enableStatisticsReporter', + value: function _enableStatisticsReporter() { + if (this._statisticsReporter == null) { + this._statisticsReporter = self.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval); + } + } + }, { + key: '_disableStatisticsReporter', + value: function _disableStatisticsReporter() { + if (this._statisticsReporter) { + self.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + } + }, { + key: '_reportSegmentMediaInfo', + value: function _reportSegmentMediaInfo(segmentIndex) { + var segmentInfo = this._mediaInfo.segments[segmentIndex]; + var exportInfo = Object.assign({}, segmentInfo); + exportInfo.duration = this._mediaInfo.duration; + exportInfo.segmentCount = this._mediaInfo.segmentCount; + delete exportInfo.segments; + delete exportInfo.keyframesIndex; + this._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, exportInfo); + } + }, { + key: '_reportStatisticsInfo', + value: function _reportStatisticsInfo() { + var info = {}; + info.url = this._ioctl.currentURL; + info.hasRedirect = this._ioctl.hasRedirect; + if (info.hasRedirect) { + info.redirectedURL = this._ioctl.currentRedirectedURL; + } + info.speed = this._ioctl.currentSpeed; + info.loaderType = this._ioctl.loaderType; + info.currentSegmentIndex = this._currentSegmentIndex; + info.totalSegmentCount = this._mediaDataSource.segments.length; + this._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, info); + } + }]); + return TransmuxingController; + }(); + exports.default = TransmuxingController; + }, { + "../demux/demux-errors.js": 16, + "../demux/flv-demuxer.js": 18, + "../io/io-controller.js": 23, + "../io/loader.js": 24, + "../remux/mp4-remuxer.js": 38, + "../utils/browser.js": 39, + "../utils/logger.js": 41, + "./media-info.js": 7, + "./transmuxing-events.js": 13, + "events": 2 + }], + 13: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var TransmuxingEvents = { + IO_ERROR: 'io_error', + DEMUX_ERROR: 'demux_error', + INIT_SEGMENT: 'init_segment', + MEDIA_SEGMENT: 'media_segment', + LOADING_COMPLETE: 'loading_complete', + RECOVERED_EARLY_EOF: 'recovered_early_eof', + MEDIA_INFO: 'media_info', + METADATA_ARRIVED: 'metadata_arrived', + SCRIPTDATA_ARRIVED: 'scriptdata_arrived', + STATISTICS_INFO: 'statistics_info', + RECOMMEND_SEEKPOINT: 'recommend_seekpoint' + }; + exports.default = TransmuxingEvents; + }, {}], + 14: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _loggingControl = _dereq_('../utils/logging-control.js'); + var _loggingControl2 = _interopRequireDefault(_loggingControl); + var _polyfill = _dereq_('../utils/polyfill.js'); + var _polyfill2 = _interopRequireDefault(_polyfill); + var _transmuxingController = _dereq_('./transmuxing-controller.js'); + var _transmuxingController2 = _interopRequireDefault(_transmuxingController); + var _transmuxingEvents = _dereq_('./transmuxing-events.js'); + var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + var TransmuxingWorker = function TransmuxingWorker(self) { + var TAG = 'TransmuxingWorker'; + var controller = null; + var logcatListener = onLogcatCallback.bind(this); + _polyfill2.default.install(); + self.addEventListener('message', function(e) { + switch (e.data.cmd) { + case 'init': + controller = new _transmuxingController2.default(e.data.param[0], e.data.param[1]); + controller.on(_transmuxingEvents2.default.IO_ERROR, onIOError.bind(this)); + controller.on(_transmuxingEvents2.default.DEMUX_ERROR, onDemuxError.bind(this)); + controller.on(_transmuxingEvents2.default.INIT_SEGMENT, onInitSegment.bind(this)); + controller.on(_transmuxingEvents2.default.MEDIA_SEGMENT, onMediaSegment.bind(this)); + controller.on(_transmuxingEvents2.default.LOADING_COMPLETE, onLoadingComplete.bind(this)); + controller.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, onRecoveredEarlyEof.bind(this)); + controller.on(_transmuxingEvents2.default.MEDIA_INFO, onMediaInfo.bind(this)); + controller.on(_transmuxingEvents2.default.METADATA_ARRIVED, onMetaDataArrived.bind(this)); + controller.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, onScriptDataArrived.bind(this)); + controller.on(_transmuxingEvents2.default.STATISTICS_INFO, onStatisticsInfo.bind(this)); + controller.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, onRecommendSeekpoint.bind(this)); + break; + case 'destroy': + if (controller) { + controller.destroy(); + controller = null; + } + self.postMessage({ + msg: 'destroyed' + }); + break; + case 'start': + controller.start(); + break; + case 'stop': + controller.stop(); + break; + case 'seek': + controller.seek(e.data.param); + break; + case 'pause': + controller.pause(); + break; + case 'resume': + controller.resume(); + break; + case 'logging_config': { + var config = e.data.param; + _loggingControl2.default.applyConfig(config); + if (config.enableCallback === true) { + _loggingControl2.default.addLogListener(logcatListener); + } else { + _loggingControl2.default.removeLogListener(logcatListener); + } + break; + } + } + }); + + function onInitSegment(type, initSegment) { + var obj = { + msg: _transmuxingEvents2.default.INIT_SEGMENT, + data: { + type: type, + data: initSegment + } + }; + self.postMessage(obj, [initSegment.data]); + } + + function onMediaSegment(type, mediaSegment) { + var obj = { + msg: _transmuxingEvents2.default.MEDIA_SEGMENT, + data: { + type: type, + data: mediaSegment + } + }; + self.postMessage(obj, [mediaSegment.data]); + } + + function onLoadingComplete() { + var obj = { + msg: _transmuxingEvents2.default.LOADING_COMPLETE + }; + self.postMessage(obj); + } + + function onRecoveredEarlyEof() { + var obj = { + msg: _transmuxingEvents2.default.RECOVERED_EARLY_EOF + }; + self.postMessage(obj); + } + + function onMediaInfo(mediaInfo) { + var obj = { + msg: _transmuxingEvents2.default.MEDIA_INFO, + data: mediaInfo + }; + self.postMessage(obj); + } + + function onMetaDataArrived(metadata) { + var obj = { + msg: _transmuxingEvents2.default.METADATA_ARRIVED, + data: metadata + }; + self.postMessage(obj); + } + + function onScriptDataArrived(data) { + var obj = { + msg: _transmuxingEvents2.default.SCRIPTDATA_ARRIVED, + data: data + }; + self.postMessage(obj); + } + + function onStatisticsInfo(statInfo) { + var obj = { + msg: _transmuxingEvents2.default.STATISTICS_INFO, + data: statInfo + }; + self.postMessage(obj); + } + + function onIOError(type, info) { + self.postMessage({ + msg: _transmuxingEvents2.default.IO_ERROR, + data: { + type: type, + info: info + } + }); + } + + function onDemuxError(type, info) { + self.postMessage({ + msg: _transmuxingEvents2.default.DEMUX_ERROR, + data: { + type: type, + info: info + } + }); + } + + function onRecommendSeekpoint(milliseconds) { + self.postMessage({ + msg: _transmuxingEvents2.default.RECOMMEND_SEEKPOINT, + data: milliseconds + }); + } + + function onLogcatCallback(type, str) { + self.postMessage({ + msg: 'logcat_callback', + data: { + type: type, + logcat: str + } + }); + } + }; + exports.default = TransmuxingWorker; + }, { + "../utils/logger.js": 41, + "../utils/logging-control.js": 42, + "../utils/polyfill.js": 43, + "./transmuxing-controller.js": 12, + "./transmuxing-events.js": 13 + }], + 15: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _utf8Conv = _dereq_('../utils/utf8-conv.js'); + var _utf8Conv2 = _interopRequireDefault(_utf8Conv); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var le = function() { + var buf = new ArrayBuffer(2); + new DataView(buf).setInt16(0, 256, true); + return new Int16Array(buf)[0] === 256; + }(); + var AMF = function() { + function AMF() { + _classCallCheck(this, AMF); + } + _createClass(AMF, null, [{ + key: 'parseScriptData', + value: function parseScriptData(arrayBuffer, dataOffset, dataSize) { + var data = {}; + try { + var name = AMF.parseValue(arrayBuffer, dataOffset, dataSize); + var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size); + data[name.data] = value.data; + } catch (e) { + _logger2.default.e('AMF', e.toString()); + } + return data; + } + }, { + key: 'parseObject', + value: function parseObject(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 3) { + throw new _exception.IllegalStateException('Data not enough when parse ScriptDataObject'); + } + var name = AMF.parseString(arrayBuffer, dataOffset, dataSize); + var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size); + var isObjectEnd = value.objectEnd; + return { + data: { + name: name.data, + value: value.data + }, + size: name.size + value.size, + objectEnd: isObjectEnd + }; + } + }, { + key: 'parseVariable', + value: function parseVariable(arrayBuffer, dataOffset, dataSize) { + return AMF.parseObject(arrayBuffer, dataOffset, dataSize); + } + }, { + key: 'parseString', + value: function parseString(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 2) { + throw new _exception.IllegalStateException('Data not enough when parse String'); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var length = v.getUint16(0, !le); + var str = void 0; + if (length > 0) { + str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 2, length)); + } else { + str = ''; + } + return { + data: str, + size: 2 + length + }; + } + }, { + key: 'parseLongString', + value: function parseLongString(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 4) { + throw new _exception.IllegalStateException('Data not enough when parse LongString'); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var length = v.getUint32(0, !le); + var str = void 0; + if (length > 0) { + str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 4, length)); + } else { + str = ''; + } + return { + data: str, + size: 4 + length + }; + } + }, { + key: 'parseDate', + value: function parseDate(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 10) { + throw new _exception.IllegalStateException('Data size invalid when parse Date'); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var timestamp = v.getFloat64(0, !le); + var localTimeOffset = v.getInt16(8, !le); + timestamp += localTimeOffset * 60 * 1000; + return { + data: new Date(timestamp), + size: 8 + 2 + }; + } + }, { + key: 'parseValue', + value: function parseValue(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 1) { + throw new _exception.IllegalStateException('Data not enough when parse Value'); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var offset = 1; + var type = v.getUint8(0); + var value = void 0; + var objectEnd = false; + try { + switch (type) { + case 0: + value = v.getFloat64(1, !le); + offset += 8; + break; + case 1: { + var b = v.getUint8(1); + value = b ? true : false; + offset += 1; + break; + } + case 2: { + var amfstr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1); + value = amfstr.data; + offset += amfstr.size; + break; + } + case 3: { + value = {}; + var terminal = 0; + if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) { + terminal = 3; + } + while (offset < dataSize - 4) { + var amfobj = AMF.parseObject(arrayBuffer, dataOffset + offset, dataSize - offset - terminal); + if (amfobj.objectEnd) break; + value[amfobj.data.name] = amfobj.data.value; + offset += amfobj.size; + } + if (offset <= dataSize - 3) { + var marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF; + if (marker === 9) { + offset += 3; + } + } + break; + } + case 8: { + value = {}; + offset += 4; + var _terminal = 0; + if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) { + _terminal = 3; + } + while (offset < dataSize - 8) { + var amfvar = AMF.parseVariable(arrayBuffer, dataOffset + offset, dataSize - offset - _terminal); + if (amfvar.objectEnd) break; + value[amfvar.data.name] = amfvar.data.value; + offset += amfvar.size; + } + if (offset <= dataSize - 3) { + var _marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF; + if (_marker === 9) { + offset += 3; + } + } + break; + } + case 9: + value = undefined; + offset = 1; + objectEnd = true; + break; + case 10: { + value = []; + var strictArrayLength = v.getUint32(1, !le); + offset += 4; + for (var i = 0; i < strictArrayLength; i++) { + var val = AMF.parseValue(arrayBuffer, dataOffset + offset, dataSize - offset); + value.push(val.data); + offset += val.size; + } + break; + } + case 11: { + var date = AMF.parseDate(arrayBuffer, dataOffset + 1, dataSize - 1); + value = date.data; + offset += date.size; + break; + } + case 12: { + var amfLongStr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1); + value = amfLongStr.data; + offset += amfLongStr.size; + break; + } + default: + offset = dataSize; + _logger2.default.w('AMF', 'Unsupported AMF value type ' + type); + } + } catch (e) { + _logger2.default.e('AMF', e.toString()); + } + return { + data: value, + size: offset, + objectEnd: objectEnd + }; + } + }]); + return AMF; + }(); + exports.default = AMF; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "../utils/utf8-conv.js": 44 + }], + 16: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var DemuxErrors = { + OK: 'OK', + FORMAT_ERROR: 'FormatError', + FORMAT_UNSUPPORTED: 'FormatUnsupported', + CODEC_UNSUPPORTED: 'CodecUnsupported' + }; + exports.default = DemuxErrors; + }, {}], + 17: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _exception = _dereq_('../utils/exception.js'); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var ExpGolomb = function() { + function ExpGolomb(uint8array) { + _classCallCheck(this, ExpGolomb); + this.TAG = 'ExpGolomb'; + this._buffer = uint8array; + this._buffer_index = 0; + this._total_bytes = uint8array.byteLength; + this._total_bits = uint8array.byteLength * 8; + this._current_word = 0; + this._current_word_bits_left = 0; + } + _createClass(ExpGolomb, [{ + key: 'destroy', + value: function destroy() { + this._buffer = null; + } + }, { + key: '_fillCurrentWord', + value: function _fillCurrentWord() { + var buffer_bytes_left = this._total_bytes - this._buffer_index; + if (buffer_bytes_left <= 0) throw new _exception.IllegalStateException('ExpGolomb: _fillCurrentWord() but no bytes available'); + var bytes_read = Math.min(4, buffer_bytes_left); + var word = new Uint8Array(4); + word.set(this._buffer.subarray(this._buffer_index, this._buffer_index + bytes_read)); + this._current_word = new DataView(word.buffer).getUint32(0, false); + this._buffer_index += bytes_read; + this._current_word_bits_left = bytes_read * 8; + } + }, { + key: 'readBits', + value: function readBits(bits) { + if (bits > 32) throw new _exception.InvalidArgumentException('ExpGolomb: readBits() bits exceeded max 32bits!'); + if (bits <= this._current_word_bits_left) { + var _result = this._current_word >>> 32 - bits; + this._current_word <<= bits; + this._current_word_bits_left -= bits; + return _result; + } + var result = this._current_word_bits_left ? this._current_word : 0; + result = result >>> 32 - this._current_word_bits_left; + var bits_need_left = bits - this._current_word_bits_left; + this._fillCurrentWord(); + var bits_read_next = Math.min(bits_need_left, this._current_word_bits_left); + var result2 = this._current_word >>> 32 - bits_read_next; + this._current_word <<= bits_read_next; + this._current_word_bits_left -= bits_read_next; + result = result << bits_read_next | result2; + return result; + } + }, { + key: 'readBool', + value: function readBool() { + return this.readBits(1) === 1; + } + }, { + key: 'readByte', + value: function readByte() { + return this.readBits(8); + } + }, { + key: '_skipLeadingZero', + value: function _skipLeadingZero() { + var zero_count = void 0; + for (zero_count = 0; zero_count < this._current_word_bits_left; zero_count++) { + if (0 !== (this._current_word & 0x80000000 >>> zero_count)) { + this._current_word <<= zero_count; + this._current_word_bits_left -= zero_count; + return zero_count; + } + } + this._fillCurrentWord(); + return zero_count + this._skipLeadingZero(); + } + }, { + key: 'readUEG', + value: function readUEG() { + var leading_zeros = this._skipLeadingZero(); + return this.readBits(leading_zeros + 1) - 1; + } + }, { + key: 'readSEG', + value: function readSEG() { + var value = this.readUEG(); + if (value & 0x01) { + return value + 1 >>> 1; + } else { + return -1 * (value >>> 1); + } + } + }]); + return ExpGolomb; + }(); + exports.default = ExpGolomb; + }, { + "../utils/exception.js": 40 + }], + 18: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _amfParser = _dereq_('./amf-parser.js'); + var _amfParser2 = _interopRequireDefault(_amfParser); + var _spsParser = _dereq_('./sps-parser.js'); + var _spsParser2 = _interopRequireDefault(_spsParser); + var _demuxErrors = _dereq_('./demux-errors.js'); + var _demuxErrors2 = _interopRequireDefault(_demuxErrors); + var _mediaInfo = _dereq_('../core/media-info.js'); + var _mediaInfo2 = _interopRequireDefault(_mediaInfo); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function Swap16(src) { + return src >>> 8 & 0xFF | (src & 0xFF) << 8; + } + + function Swap32(src) { + return (src & 0xFF000000) >>> 24 | (src & 0x00FF0000) >>> 8 | (src & 0x0000FF00) << 8 | (src & 0x000000FF) << 24; + } + + function ReadBig32(array, index) { + return array[index] << 24 | array[index + 1] << 16 | array[index + 2] << 8 | array[index + 3]; + } + var FLVDemuxer = function() { + function FLVDemuxer(probeData, config) { + _classCallCheck(this, FLVDemuxer); + this.TAG = 'FLVDemuxer'; + this._config = config; + this._onError = null; + this._onMediaInfo = null; + this._onMetaDataArrived = null; + this._onScriptDataArrived = null; + this._onTrackMetadata = null; + this._onDataAvailable = null; + this._dataOffset = probeData.dataOffset; + this._firstParse = true; + this._dispatch = false; + this._hasAudio = probeData.hasAudioTrack; + this._hasVideo = probeData.hasVideoTrack; + this._hasAudioFlagOverrided = false; + this._hasVideoFlagOverrided = false; + this._audioInitialMetadataDispatched = false; + this._videoInitialMetadataDispatched = false; + this._mediaInfo = new _mediaInfo2.default(); + this._mediaInfo.hasAudio = this._hasAudio; + this._mediaInfo.hasVideo = this._hasVideo; + this._metadata = null; + this._audioMetadata = null; + this._videoMetadata = null; + this._naluLengthSize = 4; + this._timestampBase = 0; + this._timescale = 1000; + this._duration = 0; + this._durationOverrided = false; + this._referenceFrameRate = { + fixed: true, + fps: 23.976, + fps_num: 23976, + fps_den: 1000 + }; + this._flvSoundRateTable = [5500, 11025, 22050, 44100, 48000]; + this._mpegSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; + this._mpegAudioV10SampleRateTable = [44100, 48000, 32000, 0]; + this._mpegAudioV20SampleRateTable = [22050, 24000, 16000, 0]; + this._mpegAudioV25SampleRateTable = [11025, 12000, 8000, 0]; + this._mpegAudioL1BitRateTable = [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1]; + this._mpegAudioL2BitRateTable = [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1]; + this._mpegAudioL3BitRateTable = [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1]; + this._videoTrack = { + type: 'video', + id: 1, + sequenceNumber: 0, + samples: [], + length: 0 + }; + this._audioTrack = { + type: 'audio', + id: 2, + sequenceNumber: 0, + samples: [], + length: 0 + }; + this._littleEndian = function() { + var buf = new ArrayBuffer(2); + new DataView(buf).setInt16(0, 256, true); + return new Int16Array(buf)[0] === 256; + }(); + } + _createClass(FLVDemuxer, [{ + key: 'destroy', + value: function destroy() { + this._mediaInfo = null; + this._metadata = null; + this._audioMetadata = null; + this._videoMetadata = null; + this._videoTrack = null; + this._audioTrack = null; + this._onError = null; + this._onMediaInfo = null; + this._onMetaDataArrived = null; + this._onScriptDataArrived = null; + this._onTrackMetadata = null; + this._onDataAvailable = null; + } + }, { + key: 'bindDataSource', + value: function bindDataSource(loader) { + loader.onDataArrival = this.parseChunks.bind(this); + return this; + } + }, { + key: 'resetMediaInfo', + value: function resetMediaInfo() { + this._mediaInfo = new _mediaInfo2.default(); + } + }, { + key: '_isInitialMetadataDispatched', + value: function _isInitialMetadataDispatched() { + if (this._hasAudio && this._hasVideo) { + return this._audioInitialMetadataDispatched && this._videoInitialMetadataDispatched; + } + if (this._hasAudio && !this._hasVideo) { + return this._audioInitialMetadataDispatched; + } + if (!this._hasAudio && this._hasVideo) { + return this._videoInitialMetadataDispatched; + } + return false; + } + }, { + key: 'parseChunks', + value: function parseChunks(chunk, byteStart) { + if (!this._onError || !this._onMediaInfo || !this._onTrackMetadata || !this._onDataAvailable) { + throw new _exception.IllegalStateException('Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified'); + } + var offset = 0; + var le = this._littleEndian; + if (byteStart === 0) { + if (chunk.byteLength > 13) { + var probeData = FLVDemuxer.probe(chunk); + offset = probeData.dataOffset; + } else { + return 0; + } + } + if (this._firstParse) { + this._firstParse = false; + if (byteStart + offset !== this._dataOffset) { + _logger2.default.w(this.TAG, 'First time parsing but chunk byteStart invalid!'); + } + var v = new DataView(chunk, offset); + var prevTagSize0 = v.getUint32(0, !le); + if (prevTagSize0 !== 0) { + _logger2.default.w(this.TAG, 'PrevTagSize0 !== 0 !!!'); + } + offset += 4; + } + while (offset < chunk.byteLength) { + this._dispatch = true; + var _v = new DataView(chunk, offset); + if (offset + 11 + 4 > chunk.byteLength) { + break; + } + var tagType = _v.getUint8(0); + var dataSize = _v.getUint32(0, !le) & 0x00FFFFFF; + if (offset + 11 + dataSize + 4 > chunk.byteLength) { + break; + } + if (tagType !== 8 && tagType !== 9 && tagType !== 18) { + _logger2.default.w(this.TAG, 'Unsupported tag type ' + tagType + ', skipped'); + offset += 11 + dataSize + 4; + continue; + } + var ts2 = _v.getUint8(4); + var ts1 = _v.getUint8(5); + var ts0 = _v.getUint8(6); + var ts3 = _v.getUint8(7); + var timestamp = ts0 | ts1 << 8 | ts2 << 16 | ts3 << 24; + var streamId = _v.getUint32(7, !le) & 0x00FFFFFF; + if (streamId !== 0) { + _logger2.default.w(this.TAG, 'Meet tag which has StreamID != 0!'); + } + var dataOffset = offset + 11; + switch (tagType) { + case 8: + this._parseAudioData(chunk, dataOffset, dataSize, timestamp); + break; + case 9: + this._parseVideoData(chunk, dataOffset, dataSize, timestamp, byteStart + offset); + break; + case 18: + this._parseScriptData(chunk, dataOffset, dataSize); + break; + } + var prevTagSize = _v.getUint32(11 + dataSize, !le); + if (prevTagSize !== 11 + dataSize) { + _logger2.default.w(this.TAG, 'Invalid PrevTagSize ' + prevTagSize); + } + offset += 11 + dataSize + 4; + } + if (this._isInitialMetadataDispatched()) { + if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } + return offset; + } + }, { + key: '_parseScriptData', + value: function _parseScriptData(arrayBuffer, dataOffset, dataSize) { + var scriptData = _amfParser2.default.parseScriptData(arrayBuffer, dataOffset, dataSize); + if (scriptData.hasOwnProperty('onMetaData')) { + if (scriptData.onMetaData == null || _typeof(scriptData.onMetaData) !== 'object') { + _logger2.default.w(this.TAG, 'Invalid onMetaData structure!'); + return; + } + if (this._metadata) { + _logger2.default.w(this.TAG, 'Found another onMetaData tag!'); + } + this._metadata = scriptData; + var onMetaData = this._metadata.onMetaData; + if (this._onMetaDataArrived) { + this._onMetaDataArrived(Object.assign({}, onMetaData)); + } + if (typeof onMetaData.hasAudio === 'boolean') { + if (this._hasAudioFlagOverrided === false) { + this._hasAudio = onMetaData.hasAudio; + this._mediaInfo.hasAudio = this._hasAudio; + } + } + if (typeof onMetaData.hasVideo === 'boolean') { + if (this._hasVideoFlagOverrided === false) { + this._hasVideo = onMetaData.hasVideo; + this._mediaInfo.hasVideo = this._hasVideo; + } + } + if (typeof onMetaData.audiodatarate === 'number') { + this._mediaInfo.audioDataRate = onMetaData.audiodatarate; + } + if (typeof onMetaData.videodatarate === 'number') { + this._mediaInfo.videoDataRate = onMetaData.videodatarate; + } + if (typeof onMetaData.width === 'number') { + this._mediaInfo.width = onMetaData.width; + } + if (typeof onMetaData.height === 'number') { + this._mediaInfo.height = onMetaData.height; + } + if (typeof onMetaData.duration === 'number') { + if (!this._durationOverrided) { + var duration = Math.floor(onMetaData.duration * this._timescale); + this._duration = duration; + this._mediaInfo.duration = duration; + } + } else { + this._mediaInfo.duration = 0; + } + if (typeof onMetaData.framerate === 'number') { + var fps_num = Math.floor(onMetaData.framerate * 1000); + if (fps_num > 0) { + var fps = fps_num / 1000; + this._referenceFrameRate.fixed = true; + this._referenceFrameRate.fps = fps; + this._referenceFrameRate.fps_num = fps_num; + this._referenceFrameRate.fps_den = 1000; + this._mediaInfo.fps = fps; + } + } + if (_typeof(onMetaData.keyframes) === 'object') { + this._mediaInfo.hasKeyframesIndex = true; + var keyframes = onMetaData.keyframes; + this._mediaInfo.keyframesIndex = this._parseKeyframesIndex(keyframes); + onMetaData.keyframes = null; + } else { + this._mediaInfo.hasKeyframesIndex = false; + } + this._dispatch = false; + this._mediaInfo.metadata = onMetaData; + _logger2.default.v(this.TAG, 'Parsed onMetaData'); + if (this._mediaInfo.isComplete()) { + this._onMediaInfo(this._mediaInfo); + } + } + if (Object.keys(scriptData).length > 0) { + if (this._onScriptDataArrived) { + this._onScriptDataArrived(Object.assign({}, scriptData)); + } + } + } + }, { + key: '_parseKeyframesIndex', + value: function _parseKeyframesIndex(keyframes) { + var times = []; + var filepositions = []; + for (var i = 1; i < keyframes.times.length; i++) { + var time = this._timestampBase + Math.floor(keyframes.times[i] * 1000); + times.push(time); + filepositions.push(keyframes.filepositions[i]); + } + return { + times: times, + filepositions: filepositions + }; + } + }, { + key: '_parseAudioData', + value: function _parseAudioData(arrayBuffer, dataOffset, dataSize, tagTimestamp) { + if (dataSize <= 1) { + _logger2.default.w(this.TAG, 'Flv: Invalid audio packet, missing SoundData payload!'); + return; + } + if (this._hasAudioFlagOverrided === true && this._hasAudio === false) { + return; + } + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var soundSpec = v.getUint8(0); + var soundFormat = soundSpec >>> 4; + if (soundFormat !== 2 && soundFormat !== 10) { + this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported audio codec idx: ' + soundFormat); + return; + } + var soundRate = 0; + var soundRateIndex = (soundSpec & 12) >>> 2; + if (soundRateIndex >= 0 && soundRateIndex <= 4) { + soundRate = this._flvSoundRateTable[soundRateIndex]; + } else { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid audio sample rate idx: ' + soundRateIndex); + return; + } + var soundSize = (soundSpec & 2) >>> 1; + var soundType = soundSpec & 1; + var meta = this._audioMetadata; + var track = this._audioTrack; + if (!meta) { + if (this._hasAudio === false && this._hasAudioFlagOverrided === false) { + this._hasAudio = true; + this._mediaInfo.hasAudio = true; + } + meta = this._audioMetadata = {}; + meta.type = 'audio'; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + meta.audioSampleRate = soundRate; + meta.channelCount = soundType === 0 ? 1 : 2; + } + if (soundFormat === 10) { + var aacData = this._parseAACAudioData(arrayBuffer, dataOffset + 1, dataSize - 1); + if (aacData == undefined) { + return; + } + if (aacData.packetType === 0) { + if (meta.config) { + _logger2.default.w(this.TAG, 'Found another AudioSpecificConfig!'); + } + var misc = aacData.data; + meta.audioSampleRate = misc.samplingRate; + meta.channelCount = misc.channelCount; + meta.codec = misc.codec; + meta.originalCodec = misc.originalCodec; + meta.config = misc.config; + meta.refSampleDuration = 1024 / meta.audioSampleRate * meta.timescale; + _logger2.default.v(this.TAG, 'Parsed AudioSpecificConfig'); + if (this._isInitialMetadataDispatched()) { + if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._audioInitialMetadataDispatched = true; + } + this._dispatch = false; + this._onTrackMetadata('audio', meta); + var mi = this._mediaInfo; + mi.audioCodec = meta.originalCodec; + mi.audioSampleRate = meta.audioSampleRate; + mi.audioChannelCount = meta.channelCount; + if (mi.hasVideo) { + if (mi.videoCodec != null) { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.audioCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + } else if (aacData.packetType === 1) { + var dts = this._timestampBase + tagTimestamp; + var aacSample = { + unit: aacData.data, + length: aacData.data.byteLength, + dts: dts, + pts: dts + }; + track.samples.push(aacSample); + track.length += aacData.data.length; + } else { + _logger2.default.e(this.TAG, 'Flv: Unsupported AAC data type ' + aacData.packetType); + } + } else if (soundFormat === 2) { + if (!meta.codec) { + var _misc = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, true); + if (_misc == undefined) { + return; + } + meta.audioSampleRate = _misc.samplingRate; + meta.channelCount = _misc.channelCount; + meta.codec = _misc.codec; + meta.originalCodec = _misc.originalCodec; + meta.refSampleDuration = 1152 / meta.audioSampleRate * meta.timescale; + _logger2.default.v(this.TAG, 'Parsed MPEG Audio Frame Header'); + this._audioInitialMetadataDispatched = true; + this._onTrackMetadata('audio', meta); + var _mi = this._mediaInfo; + _mi.audioCodec = meta.codec; + _mi.audioSampleRate = meta.audioSampleRate; + _mi.audioChannelCount = meta.channelCount; + _mi.audioDataRate = _misc.bitRate; + if (_mi.hasVideo) { + if (_mi.videoCodec != null) { + _mi.mimeType = 'video/x-flv; codecs="' + _mi.videoCodec + ',' + _mi.audioCodec + '"'; + } + } else { + _mi.mimeType = 'video/x-flv; codecs="' + _mi.audioCodec + '"'; + } + if (_mi.isComplete()) { + this._onMediaInfo(_mi); + } + } + var data = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, false); + if (data == undefined) { + return; + } + var _dts = this._timestampBase + tagTimestamp; + var mp3Sample = { + unit: data, + length: data.byteLength, + dts: _dts, + pts: _dts + }; + track.samples.push(mp3Sample); + track.length += data.length; + } + } + }, { + key: '_parseAACAudioData', + value: function _parseAACAudioData(arrayBuffer, dataOffset, dataSize) { + if (dataSize <= 1) { + _logger2.default.w(this.TAG, 'Flv: Invalid AAC packet, missing AACPacketType or/and Data!'); + return; + } + var result = {}; + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + result.packetType = array[0]; + if (array[0] === 0) { + result.data = this._parseAACAudioSpecificConfig(arrayBuffer, dataOffset + 1, dataSize - 1); + } else { + result.data = array.subarray(1); + } + return result; + } + }, { + key: '_parseAACAudioSpecificConfig', + value: function _parseAACAudioSpecificConfig(arrayBuffer, dataOffset, dataSize) { + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + var config = null; + var audioObjectType = 0; + var originalAudioObjectType = 0; + var audioExtensionObjectType = null; + var samplingIndex = 0; + var extensionSamplingIndex = null; + audioObjectType = originalAudioObjectType = array[0] >>> 3; + samplingIndex = (array[0] & 0x07) << 1 | array[1] >>> 7; + if (samplingIndex < 0 || samplingIndex >= this._mpegSamplingRates.length) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid sampling frequency index!'); + return; + } + var samplingFrequence = this._mpegSamplingRates[samplingIndex]; + var channelConfig = (array[1] & 0x78) >>> 3; + if (channelConfig < 0 || channelConfig >= 8) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid channel configuration'); + return; + } + if (audioObjectType === 5) { + extensionSamplingIndex = (array[1] & 0x07) << 1 | array[2] >>> 7; + audioExtensionObjectType = (array[2] & 0x7C) >>> 2; + } + var userAgent = self.navigator.userAgent.toLowerCase(); + if (userAgent.indexOf('firefox') !== -1) { + if (samplingIndex >= 6) { + audioObjectType = 5; + config = new Array(4); + extensionSamplingIndex = samplingIndex - 3; + } else { + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } + } else if (userAgent.indexOf('android') !== -1) { + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } else { + audioObjectType = 5; + extensionSamplingIndex = samplingIndex; + config = new Array(4); + if (samplingIndex >= 6) { + extensionSamplingIndex = samplingIndex - 3; + } else if (channelConfig === 1) { + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } + } + config[0] = audioObjectType << 3; + config[0] |= (samplingIndex & 0x0F) >>> 1; + config[1] = (samplingIndex & 0x0F) << 7; + config[1] |= (channelConfig & 0x0F) << 3; + if (audioObjectType === 5) { + config[1] |= (extensionSamplingIndex & 0x0F) >>> 1; + config[2] = (extensionSamplingIndex & 0x01) << 7; + config[2] |= 2 << 2; + config[3] = 0; + } + return { + config: config, + samplingRate: samplingFrequence, + channelCount: channelConfig, + codec: 'mp4a.40.' + audioObjectType, + originalCodec: 'mp4a.40.' + originalAudioObjectType + }; + } + }, { + key: '_parseMP3AudioData', + value: function _parseMP3AudioData(arrayBuffer, dataOffset, dataSize, requestHeader) { + if (dataSize < 4) { + _logger2.default.w(this.TAG, 'Flv: Invalid MP3 packet, header missing!'); + return; + } + var le = this._littleEndian; + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + var result = null; + if (requestHeader) { + if (array[0] !== 0xFF) { + return; + } + var ver = array[1] >>> 3 & 0x03; + var layer = (array[1] & 0x06) >> 1; + var bitrate_index = (array[2] & 0xF0) >>> 4; + var sampling_freq_index = (array[2] & 0x0C) >>> 2; + var channel_mode = array[3] >>> 6 & 0x03; + var channel_count = channel_mode !== 3 ? 2 : 1; + var sample_rate = 0; + var bit_rate = 0; + var object_type = 34; + var codec = 'mp3'; + switch (ver) { + case 0: + sample_rate = this._mpegAudioV25SampleRateTable[sampling_freq_index]; + break; + case 2: + sample_rate = this._mpegAudioV20SampleRateTable[sampling_freq_index]; + break; + case 3: + sample_rate = this._mpegAudioV10SampleRateTable[sampling_freq_index]; + break; + } + switch (layer) { + case 1: + object_type = 34; + if (bitrate_index < this._mpegAudioL3BitRateTable.length) { + bit_rate = this._mpegAudioL3BitRateTable[bitrate_index]; + } + break; + case 2: + object_type = 33; + if (bitrate_index < this._mpegAudioL2BitRateTable.length) { + bit_rate = this._mpegAudioL2BitRateTable[bitrate_index]; + } + break; + case 3: + object_type = 32; + if (bitrate_index < this._mpegAudioL1BitRateTable.length) { + bit_rate = this._mpegAudioL1BitRateTable[bitrate_index]; + } + break; + } + result = { + bitRate: bit_rate, + samplingRate: sample_rate, + channelCount: channel_count, + codec: codec, + originalCodec: codec + }; + } else { + result = array; + } + return result; + } + }, { + key: '_parseVideoData', + value: function _parseVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition) { + if (dataSize <= 1) { + _logger2.default.w(this.TAG, 'Flv: Invalid video packet, missing VideoData payload!'); + return; + } + if (this._hasVideoFlagOverrided === true && this._hasVideo === false) { + return; + } + var spec = new Uint8Array(arrayBuffer, dataOffset, dataSize)[0]; + var frameType = (spec & 240) >>> 4; + var codecId = spec & 15; + if (codecId !== 7) { + this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported codec in video frame: ' + codecId); + return; + } + this._parseAVCVideoPacket(arrayBuffer, dataOffset + 1, dataSize - 1, tagTimestamp, tagPosition, frameType); + } + }, { + key: '_parseAVCVideoPacket', + value: function _parseAVCVideoPacket(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType) { + if (dataSize < 4) { + _logger2.default.w(this.TAG, 'Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime'); + return; + } + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var packetType = v.getUint8(0); + var cts_unsigned = v.getUint32(0, !le) & 0x00FFFFFF; + var cts = cts_unsigned << 8 >> 8; + if (packetType === 0) { + this._parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset + 4, dataSize - 4); + } else if (packetType === 1) { + this._parseAVCVideoData(arrayBuffer, dataOffset + 4, dataSize - 4, tagTimestamp, tagPosition, frameType, cts); + } else if (packetType === 2) {} else { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid video packet type ' + packetType); + return; + } + } + }, { + key: '_parseAVCDecoderConfigurationRecord', + value: function _parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset, dataSize) { + if (dataSize < 7) { + _logger2.default.w(this.TAG, 'Flv: Invalid AVCDecoderConfigurationRecord, lack of data!'); + return; + } + var meta = this._videoMetadata; + var track = this._videoTrack; + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (!meta) { + if (this._hasVideo === false && this._hasVideoFlagOverrided === false) { + this._hasVideo = true; + this._mediaInfo.hasVideo = true; + } + meta = this._videoMetadata = {}; + meta.type = 'video'; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + } else { + if (typeof meta.avcc !== 'undefined') { + _logger2.default.w(this.TAG, 'Found another AVCDecoderConfigurationRecord!'); + } + } + var version = v.getUint8(0); + var avcProfile = v.getUint8(1); + var profileCompatibility = v.getUint8(2); + var avcLevel = v.getUint8(3); + if (version !== 1 || avcProfile === 0) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord'); + return; + } + this._naluLengthSize = (v.getUint8(4) & 3) + 1; + if (this._naluLengthSize !== 3 && this._naluLengthSize !== 4) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Strange NaluLengthSizeMinusOne: ' + (this._naluLengthSize - 1)); + return; + } + var spsCount = v.getUint8(5) & 31; + if (spsCount === 0) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No SPS'); + return; + } else if (spsCount > 1) { + _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: SPS Count = ' + spsCount); + } + var offset = 6; + for (var i = 0; i < spsCount; i++) { + var len = v.getUint16(offset, !le); + offset += 2; + if (len === 0) { + continue; + } + var sps = new Uint8Array(arrayBuffer, dataOffset + offset, len); + offset += len; + var config = _spsParser2.default.parseSPS(sps); + if (i !== 0) { + continue; + } + meta.codecWidth = config.codec_size.width; + meta.codecHeight = config.codec_size.height; + meta.presentWidth = config.present_size.width; + meta.presentHeight = config.present_size.height; + meta.profile = config.profile_string; + meta.level = config.level_string; + meta.bitDepth = config.bit_depth; + meta.chromaFormat = config.chroma_format; + meta.sarRatio = config.sar_ratio; + meta.frameRate = config.frame_rate; + if (config.frame_rate.fixed === false || config.frame_rate.fps_num === 0 || config.frame_rate.fps_den === 0) { + meta.frameRate = this._referenceFrameRate; + } + var fps_den = meta.frameRate.fps_den; + var fps_num = meta.frameRate.fps_num; + meta.refSampleDuration = meta.timescale * (fps_den / fps_num); + var codecArray = sps.subarray(1, 4); + var codecString = 'avc1.'; + for (var j = 0; j < 3; j++) { + var h = codecArray[j].toString(16); + if (h.length < 2) { + h = '0' + h; + } + codecString += h; + } + meta.codec = codecString; + var mi = this._mediaInfo; + mi.width = meta.codecWidth; + mi.height = meta.codecHeight; + mi.fps = meta.frameRate.fps; + mi.profile = meta.profile; + mi.level = meta.level; + mi.refFrames = config.ref_frames; + mi.chromaFormat = config.chroma_format_string; + mi.sarNum = meta.sarRatio.width; + mi.sarDen = meta.sarRatio.height; + mi.videoCodec = codecString; + if (mi.hasAudio) { + if (mi.audioCodec != null) { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + } + var ppsCount = v.getUint8(offset); + if (ppsCount === 0) { + this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No PPS'); + return; + } else if (ppsCount > 1) { + _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: PPS Count = ' + ppsCount); + } + offset++; + for (var _i = 0; _i < ppsCount; _i++) { + var _len = v.getUint16(offset, !le); + offset += 2; + if (_len === 0) { + continue; + } + offset += _len; + } + meta.avcc = new Uint8Array(dataSize); + meta.avcc.set(new Uint8Array(arrayBuffer, dataOffset, dataSize), 0); + _logger2.default.v(this.TAG, 'Parsed AVCDecoderConfigurationRecord'); + if (this._isInitialMetadataDispatched()) { + if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._videoInitialMetadataDispatched = true; + } + this._dispatch = false; + this._onTrackMetadata('video', meta); + } + }, { + key: '_parseAVCVideoData', + value: function _parseAVCVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType, cts) { + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var units = [], + length = 0; + var offset = 0; + var lengthSize = this._naluLengthSize; + var dts = this._timestampBase + tagTimestamp; + var keyframe = frameType === 1; + while (offset < dataSize) { + if (offset + 4 >= dataSize) { + _logger2.default.w(this.TAG, 'Malformed Nalu near timestamp ' + dts + ', offset = ' + offset + ', dataSize = ' + dataSize); + break; + } + var naluSize = v.getUint32(offset, !le); + if (lengthSize === 3) { + naluSize >>>= 8; + } + if (naluSize > dataSize - lengthSize) { + _logger2.default.w(this.TAG, 'Malformed Nalus near timestamp ' + dts + ', NaluSize > DataSize!'); + return; + } + var unitType = v.getUint8(offset + lengthSize) & 0x1F; + if (unitType === 5) { + keyframe = true; + } + var data = new Uint8Array(arrayBuffer, dataOffset + offset, lengthSize + naluSize); + var unit = { + type: unitType, + data: data + }; + units.push(unit); + length += data.byteLength; + offset += lengthSize + naluSize; + } + if (units.length) { + var track = this._videoTrack; + var avcSample = { + units: units, + length: length, + isKeyframe: keyframe, + dts: dts, + cts: cts, + pts: dts + cts + }; + if (keyframe) { + avcSample.fileposition = tagPosition; + } + track.samples.push(avcSample); + track.length += length; + } + } + }, { + key: 'onTrackMetadata', + get: function get() { + return this._onTrackMetadata; + }, + set: function set(callback) { + this._onTrackMetadata = callback; + } + }, { + key: 'onMediaInfo', + get: function get() { + return this._onMediaInfo; + }, + set: function set(callback) { + this._onMediaInfo = callback; + } + }, { + key: 'onMetaDataArrived', + get: function get() { + return this._onMetaDataArrived; + }, + set: function set(callback) { + this._onMetaDataArrived = callback; + } + }, { + key: 'onScriptDataArrived', + get: function get() { + return this._onScriptDataArrived; + }, + set: function set(callback) { + this._onScriptDataArrived = callback; + } + }, { + key: 'onError', + get: function get() { + return this._onError; + }, + set: function set(callback) { + this._onError = callback; + } + }, { + key: 'onDataAvailable', + get: function get() { + return this._onDataAvailable; + }, + set: function set(callback) { + this._onDataAvailable = callback; + } + }, { + key: 'timestampBase', + get: function get() { + return this._timestampBase; + }, + set: function set(base) { + this._timestampBase = base; + } + }, { + key: 'overridedDuration', + get: function get() { + return this._duration; + }, + set: function set(duration) { + this._durationOverrided = true; + this._duration = duration; + this._mediaInfo.duration = duration; + } + }, { + key: 'overridedHasAudio', + set: function set(hasAudio) { + this._hasAudioFlagOverrided = true; + this._hasAudio = hasAudio; + this._mediaInfo.hasAudio = hasAudio; + } + }, { + key: 'overridedHasVideo', + set: function set(hasVideo) { + this._hasVideoFlagOverrided = true; + this._hasVideo = hasVideo; + this._mediaInfo.hasVideo = hasVideo; + } + }], [{ + key: 'probe', + value: function probe(buffer) { + var data = new Uint8Array(buffer); + var mismatch = { + match: false + }; + if (data[0] !== 0x46 || data[1] !== 0x4C || data[2] !== 0x56 || data[3] !== 0x01) { + return mismatch; + } + var hasAudio = (data[4] & 4) >>> 2 !== 0; + var hasVideo = (data[4] & 1) !== 0; + var offset = ReadBig32(data, 5); + if (offset < 9) { + return mismatch; + } + return { + match: true, + consumed: offset, + dataOffset: offset, + hasAudioTrack: hasAudio, + hasVideoTrack: hasVideo + }; + } + }]); + return FLVDemuxer; + }(); + exports.default = FLVDemuxer; + }, { + "../core/media-info.js": 7, + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./amf-parser.js": 15, + "./demux-errors.js": 16, + "./sps-parser.js": 19 + }], + 19: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _expGolomb = _dereq_('./exp-golomb.js'); + var _expGolomb2 = _interopRequireDefault(_expGolomb); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var SPSParser = function() { + function SPSParser() { + _classCallCheck(this, SPSParser); + } + _createClass(SPSParser, null, [{ + key: '_ebsp2rbsp', + value: function _ebsp2rbsp(uint8array) { + var src = uint8array; + var src_length = src.byteLength; + var dst = new Uint8Array(src_length); + var dst_idx = 0; + for (var i = 0; i < src_length; i++) { + if (i >= 2) { + if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) { + continue; + } + } + dst[dst_idx] = src[i]; + dst_idx++; + } + return new Uint8Array(dst.buffer, 0, dst_idx); + } + }, { + key: 'parseSPS', + value: function parseSPS(uint8array) { + var rbsp = SPSParser._ebsp2rbsp(uint8array); + var gb = new _expGolomb2.default(rbsp); + gb.readByte(); + var profile_idc = gb.readByte(); + gb.readByte(); + var level_idc = gb.readByte(); + gb.readUEG(); + var profile_string = SPSParser.getProfileString(profile_idc); + var level_string = SPSParser.getLevelString(level_idc); + var chroma_format_idc = 1; + var chroma_format = 420; + var chroma_format_table = [0, 420, 422, 444]; + var bit_depth = 8; + if (profile_idc === 100 || profile_idc === 110 || profile_idc === 122 || profile_idc === 244 || profile_idc === 44 || profile_idc === 83 || profile_idc === 86 || profile_idc === 118 || profile_idc === 128 || profile_idc === 138 || profile_idc === 144) { + chroma_format_idc = gb.readUEG(); + if (chroma_format_idc === 3) { + gb.readBits(1); + } + if (chroma_format_idc <= 3) { + chroma_format = chroma_format_table[chroma_format_idc]; + } + bit_depth = gb.readUEG() + 8; + gb.readUEG(); + gb.readBits(1); + if (gb.readBool()) { + var scaling_list_count = chroma_format_idc !== 3 ? 8 : 12; + for (var i = 0; i < scaling_list_count; i++) { + if (gb.readBool()) { + if (i < 6) { + SPSParser._skipScalingList(gb, 16); + } else { + SPSParser._skipScalingList(gb, 64); + } + } + } + } + } + gb.readUEG(); + var pic_order_cnt_type = gb.readUEG(); + if (pic_order_cnt_type === 0) { + gb.readUEG(); + } else if (pic_order_cnt_type === 1) { + gb.readBits(1); + gb.readSEG(); + gb.readSEG(); + var num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG(); + for (var _i = 0; _i < num_ref_frames_in_pic_order_cnt_cycle; _i++) { + gb.readSEG(); + } + } + var ref_frames = gb.readUEG(); + gb.readBits(1); + var pic_width_in_mbs_minus1 = gb.readUEG(); + var pic_height_in_map_units_minus1 = gb.readUEG(); + var frame_mbs_only_flag = gb.readBits(1); + if (frame_mbs_only_flag === 0) { + gb.readBits(1); + } + gb.readBits(1); + var frame_crop_left_offset = 0; + var frame_crop_right_offset = 0; + var frame_crop_top_offset = 0; + var frame_crop_bottom_offset = 0; + var frame_cropping_flag = gb.readBool(); + if (frame_cropping_flag) { + frame_crop_left_offset = gb.readUEG(); + frame_crop_right_offset = gb.readUEG(); + frame_crop_top_offset = gb.readUEG(); + frame_crop_bottom_offset = gb.readUEG(); + } + var sar_width = 1, + sar_height = 1; + var fps = 0, + fps_fixed = true, + fps_num = 0, + fps_den = 0; + var vui_parameters_present_flag = gb.readBool(); + if (vui_parameters_present_flag) { + if (gb.readBool()) { + var aspect_ratio_idc = gb.readByte(); + var sar_w_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2]; + var sar_h_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1]; + if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) { + sar_width = sar_w_table[aspect_ratio_idc - 1]; + sar_height = sar_h_table[aspect_ratio_idc - 1]; + } else if (aspect_ratio_idc === 255) { + sar_width = gb.readByte() << 8 | gb.readByte(); + sar_height = gb.readByte() << 8 | gb.readByte(); + } + } + if (gb.readBool()) { + gb.readBool(); + } + if (gb.readBool()) { + gb.readBits(4); + if (gb.readBool()) { + gb.readBits(24); + } + } + if (gb.readBool()) { + gb.readUEG(); + gb.readUEG(); + } + if (gb.readBool()) { + var num_units_in_tick = gb.readBits(32); + var time_scale = gb.readBits(32); + fps_fixed = gb.readBool(); + fps_num = time_scale; + fps_den = num_units_in_tick * 2; + fps = fps_num / fps_den; + } + } + var sarScale = 1; + if (sar_width !== 1 || sar_height !== 1) { + sarScale = sar_width / sar_height; + } + var crop_unit_x = 0, + crop_unit_y = 0; + if (chroma_format_idc === 0) { + crop_unit_x = 1; + crop_unit_y = 2 - frame_mbs_only_flag; + } else { + var sub_wc = chroma_format_idc === 3 ? 1 : 2; + var sub_hc = chroma_format_idc === 1 ? 2 : 1; + crop_unit_x = sub_wc; + crop_unit_y = sub_hc * (2 - frame_mbs_only_flag); + } + var codec_width = (pic_width_in_mbs_minus1 + 1) * 16; + var codec_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16); + codec_width -= (frame_crop_left_offset + frame_crop_right_offset) * crop_unit_x; + codec_height -= (frame_crop_top_offset + frame_crop_bottom_offset) * crop_unit_y; + var present_width = Math.ceil(codec_width * sarScale); + gb.destroy(); + gb = null; + return { + profile_string: profile_string, + level_string: level_string, + bit_depth: bit_depth, + ref_frames: ref_frames, + chroma_format: chroma_format, + chroma_format_string: SPSParser.getChromaFormatString(chroma_format), + frame_rate: { + fixed: fps_fixed, + fps: fps, + fps_den: fps_den, + fps_num: fps_num + }, + sar_ratio: { + width: sar_width, + height: sar_height + }, + codec_size: { + width: codec_width, + height: codec_height + }, + present_size: { + width: present_width, + height: codec_height + } + }; + } + }, { + key: '_skipScalingList', + value: function _skipScalingList(gb, count) { + var last_scale = 8, + next_scale = 8; + var delta_scale = 0; + for (var i = 0; i < count; i++) { + if (next_scale !== 0) { + delta_scale = gb.readSEG(); + next_scale = (last_scale + delta_scale + 256) % 256; + } + last_scale = next_scale === 0 ? last_scale : next_scale; + } + } + }, { + key: 'getProfileString', + value: function getProfileString(profile_idc) { + switch (profile_idc) { + case 66: + return 'Baseline'; + case 77: + return 'Main'; + case 88: + return 'Extended'; + case 100: + return 'High'; + case 110: + return 'High10'; + case 122: + return 'High422'; + case 244: + return 'High444'; + default: + return 'Unknown'; + } + } + }, { + key: 'getLevelString', + value: function getLevelString(level_idc) { + return (level_idc / 10).toFixed(1); + } + }, { + key: 'getChromaFormatString', + value: function getChromaFormatString(chroma) { + switch (chroma) { + case 420: + return '4:2:0'; + case 422: + return '4:2:2'; + case 444: + return '4:4:4'; + default: + return 'Unknown'; + } + } + }]); + return SPSParser; + }(); + exports.default = SPSParser; + }, { + "./exp-golomb.js": 17 + }], + 20: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _polyfill = _dereq_('./utils/polyfill.js'); + var _polyfill2 = _interopRequireDefault(_polyfill); + var _features = _dereq_('./core/features.js'); + var _features2 = _interopRequireDefault(_features); + var _loader = _dereq_('./io/loader.js'); + var _flvPlayer = _dereq_('./player/flv-player.js'); + var _flvPlayer2 = _interopRequireDefault(_flvPlayer); + var _nativePlayer = _dereq_('./player/native-player.js'); + var _nativePlayer2 = _interopRequireDefault(_nativePlayer); + var _playerEvents = _dereq_('./player/player-events.js'); + var _playerEvents2 = _interopRequireDefault(_playerEvents); + var _playerErrors = _dereq_('./player/player-errors.js'); + var _loggingControl = _dereq_('./utils/logging-control.js'); + var _loggingControl2 = _interopRequireDefault(_loggingControl); + var _exception = _dereq_('./utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + _polyfill2.default.install(); + + function createPlayer(mediaDataSource, optionalConfig) { + var mds = mediaDataSource; + if (mds == null || (typeof mds === 'undefined' ? 'undefined' : _typeof(mds)) !== 'object') { + throw new _exception.InvalidArgumentException('MediaDataSource must be an javascript object!'); + } + if (!mds.hasOwnProperty('type')) { + throw new _exception.InvalidArgumentException('MediaDataSource must has type field to indicate video file type!'); + } + switch (mds.type) { + case 'flv': + return new _flvPlayer2.default(mds, optionalConfig); + default: + return new _nativePlayer2.default(mds, optionalConfig); + } + } + + function isSupported() { + return _features2.default.supportMSEH264Playback(); + } + + function getFeatureList() { + return _features2.default.getFeatureList(); + } + var flvjs = {}; + flvjs.createPlayer = createPlayer; + flvjs.isSupported = isSupported; + flvjs.getFeatureList = getFeatureList; + flvjs.BaseLoader = _loader.BaseLoader; + flvjs.LoaderStatus = _loader.LoaderStatus; + flvjs.LoaderErrors = _loader.LoaderErrors; + flvjs.Events = _playerEvents2.default; + flvjs.ErrorTypes = _playerErrors.ErrorTypes; + flvjs.ErrorDetails = _playerErrors.ErrorDetails; + flvjs.FlvPlayer = _flvPlayer2.default; + flvjs.NativePlayer = _nativePlayer2.default; + flvjs.LoggingControl = _loggingControl2.default; + Object.defineProperty(flvjs, 'version', { + enumerable: true, + get: function get() { + return '1.5.0'; + } + }); + exports.default = flvjs; + }, { + "./core/features.js": 6, + "./io/loader.js": 24, + "./player/flv-player.js": 32, + "./player/native-player.js": 33, + "./player/player-errors.js": 34, + "./player/player-events.js": 35, + "./utils/exception.js": 40, + "./utils/logging-control.js": 42, + "./utils/polyfill.js": 43 + }], + 21: [function(_dereq_, module, exports) { + 'use strict'; + module.exports = _dereq_('./flv.js').default; + }, { + "./flv.js": 20 + }], + 22: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _browser = _dereq_('../utils/browser.js'); + var _browser2 = _interopRequireDefault(_browser); + var _loader = _dereq_('./loader.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + var FetchStreamLoader = function(_BaseLoader) { + _inherits(FetchStreamLoader, _BaseLoader); + _createClass(FetchStreamLoader, null, [{ + key: 'isSupported', + value: function isSupported() { + try { + var isWorkWellEdge = _browser2.default.msedge && _browser2.default.version.minor >= 15048; + var browserNotBlacklisted = _browser2.default.msedge ? isWorkWellEdge : true; + return self.fetch && self.ReadableStream && browserNotBlacklisted; + } catch (e) { + return false; + } + } + }]); + + function FetchStreamLoader(seekHandler, config) { + _classCallCheck(this, FetchStreamLoader); + var _this = _possibleConstructorReturn(this, (FetchStreamLoader.__proto__ || Object.getPrototypeOf(FetchStreamLoader)).call(this, 'fetch-stream-loader')); + _this.TAG = 'FetchStreamLoader'; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = true; + _this._requestAbort = false; + _this._contentLength = null; + _this._receivedLength = 0; + return _this; + } + _createClass(FetchStreamLoader, [{ + key: 'destroy', + value: function destroy() { + if (this.isWorking()) { + this.abort(); + } + _get(FetchStreamLoader.prototype.__proto__ || Object.getPrototypeOf(FetchStreamLoader.prototype), 'destroy', this).call(this); + } + }, { + key: 'open', + value: function open(dataSource, range) { + var _this2 = this; + this._dataSource = dataSource; + this._range = range; + var sourceURL = dataSource.url; + if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) { + sourceURL = dataSource.redirectedURL; + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + var headers = new self.Headers(); + if (_typeof(seekConfig.headers) === 'object') { + var configHeaders = seekConfig.headers; + for (var key in configHeaders) { + if (configHeaders.hasOwnProperty(key)) { + headers.append(key, configHeaders[key]); + } + } + } + var params = { + method: 'GET', + headers: headers, + mode: 'cors', + cache: 'default', + referrerPolicy: 'no-referrer-when-downgrade' + }; + if (_typeof(this._config.headers) === 'object') { + for (var _key in this._config.headers) { + headers.append(_key, this._config.headers[_key]); + } + } + if (dataSource.cors === false) { + params.mode = 'same-origin'; + } + if (dataSource.withCredentials) { + params.credentials = 'include'; + } + if (dataSource.referrerPolicy) { + params.referrerPolicy = dataSource.referrerPolicy; + } + this._status = _loader.LoaderStatus.kConnecting; + self.fetch(seekConfig.url, params).then(function(res) { + if (_this2._requestAbort) { + _this2._requestAbort = false; + _this2._status = _loader.LoaderStatus.kIdle; + return; + } + if (res.ok && res.status >= 200 && res.status <= 299) { + if (res.url !== seekConfig.url) { + if (_this2._onURLRedirect) { + var redirectedURL = _this2._seekHandler.removeURLParameters(res.url); + _this2._onURLRedirect(redirectedURL); + } + } + var lengthHeader = res.headers.get('Content-Length'); + if (lengthHeader != null) { + _this2._contentLength = parseInt(lengthHeader); + if (_this2._contentLength !== 0) { + if (_this2._onContentLengthKnown) { + _this2._onContentLengthKnown(_this2._contentLength); + } + } + } + return _this2._pump.call(_this2, res.body.getReader()); + } else { + _this2._status = _loader.LoaderStatus.kError; + if (_this2._onError) { + _this2._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { + code: res.status, + msg: res.statusText + }); + } else { + throw new _exception.RuntimeException('FetchStreamLoader: Http code invalid, ' + res.status + ' ' + res.statusText); + } + } + }).catch(function(e) { + _this2._status = _loader.LoaderStatus.kError; + if (_this2._onError) { + _this2._onError(_loader.LoaderErrors.EXCEPTION, { + code: -1, + msg: e.message + }); + } else { + throw e; + } + }); + } + }, { + key: 'abort', + value: function abort() { + this._requestAbort = true; + } + }, { + key: '_pump', + value: function _pump(reader) { + var _this3 = this; + return reader.read().then(function(result) { + if (result.done) { + if (_this3._contentLength !== null && _this3._receivedLength < _this3._contentLength) { + _this3._status = _loader.LoaderStatus.kError; + var type = _loader.LoaderErrors.EARLY_EOF; + var info = { + code: -1, + msg: 'Fetch stream meet Early-EOF' + }; + if (_this3._onError) { + _this3._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } else { + _this3._status = _loader.LoaderStatus.kComplete; + if (_this3._onComplete) { + _this3._onComplete(_this3._range.from, _this3._range.from + _this3._receivedLength - 1); + } + } + } else { + if (_this3._requestAbort === true) { + _this3._requestAbort = false; + _this3._status = _loader.LoaderStatus.kComplete; + return reader.cancel(); + } + _this3._status = _loader.LoaderStatus.kBuffering; + var chunk = result.value.buffer; + var byteStart = _this3._range.from + _this3._receivedLength; + _this3._receivedLength += chunk.byteLength; + if (_this3._onDataArrival) { + _this3._onDataArrival(chunk, byteStart, _this3._receivedLength); + } + _this3._pump(reader); + } + }).catch(function(e) { + if (e.code === 11 && _browser2.default.msedge) { + return; + } + _this3._status = _loader.LoaderStatus.kError; + var type = 0; + var info = null; + if ((e.code === 19 || e.message === 'network error') && (_this3._contentLength === null || _this3._contentLength !== null && _this3._receivedLength < _this3._contentLength)) { + type = _loader.LoaderErrors.EARLY_EOF; + info = { + code: e.code, + msg: 'Fetch stream meet Early-EOF' + }; + } else { + type = _loader.LoaderErrors.EXCEPTION; + info = { + code: e.code, + msg: e.message + }; + } + if (_this3._onError) { + _this3._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + }); + } + }]); + return FetchStreamLoader; + }(_loader.BaseLoader); + exports.default = FetchStreamLoader; + }, { + "../utils/browser.js": 39, + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./loader.js": 24 + }], + 23: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _speedSampler = _dereq_('./speed-sampler.js'); + var _speedSampler2 = _interopRequireDefault(_speedSampler); + var _loader = _dereq_('./loader.js'); + var _fetchStreamLoader = _dereq_('./fetch-stream-loader.js'); + var _fetchStreamLoader2 = _interopRequireDefault(_fetchStreamLoader); + var _xhrMozChunkedLoader = _dereq_('./xhr-moz-chunked-loader.js'); + var _xhrMozChunkedLoader2 = _interopRequireDefault(_xhrMozChunkedLoader); + var _xhrMsstreamLoader = _dereq_('./xhr-msstream-loader.js'); + var _xhrMsstreamLoader2 = _interopRequireDefault(_xhrMsstreamLoader); + var _xhrRangeLoader = _dereq_('./xhr-range-loader.js'); + var _xhrRangeLoader2 = _interopRequireDefault(_xhrRangeLoader); + var _websocketLoader = _dereq_('./websocket-loader.js'); + var _websocketLoader2 = _interopRequireDefault(_websocketLoader); + var _rangeSeekHandler = _dereq_('./range-seek-handler.js'); + var _rangeSeekHandler2 = _interopRequireDefault(_rangeSeekHandler); + var _paramSeekHandler = _dereq_('./param-seek-handler.js'); + var _paramSeekHandler2 = _interopRequireDefault(_paramSeekHandler); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var IOController = function() { + function IOController(dataSource, config, extraData) { + _classCallCheck(this, IOController); + this.TAG = 'IOController'; + this._config = config; + this._extraData = extraData; + this._stashInitialSize = 1024 * 384; + if (config.stashInitialSize != undefined && config.stashInitialSize > 0) { + this._stashInitialSize = config.stashInitialSize; + } + this._stashUsed = 0; + this._stashSize = this._stashInitialSize; + this._bufferSize = 1024 * 1024 * 3; + this._stashBuffer = new ArrayBuffer(this._bufferSize); + this._stashByteStart = 0; + this._enableStash = true; + if (config.enableStashBuffer === false) { + this._enableStash = false; + } + this._loader = null; + this._loaderClass = null; + this._seekHandler = null; + this._dataSource = dataSource; + this._isWebSocketURL = /wss?:\/\/(.+?)/.test(dataSource.url); + this._refTotalLength = dataSource.filesize ? dataSource.filesize : null; + this._totalLength = this._refTotalLength; + this._fullRequestFlag = false; + this._currentRange = null; + this._redirectedURL = null; + this._speedNormalized = 0; + this._speedSampler = new _speedSampler2.default(); + this._speedNormalizeList = [64, 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096]; + this._isEarlyEofReconnecting = false; + this._paused = false; + this._resumeFrom = 0; + this._onDataArrival = null; + this._onSeeked = null; + this._onError = null; + this._onComplete = null; + this._onRedirect = null; + this._onRecoveredEarlyEof = null; + this._selectSeekHandler(); + this._selectLoader(); + this._createLoader(); + } + _createClass(IOController, [{ + key: 'destroy', + value: function destroy() { + if (this._loader.isWorking()) { + this._loader.abort(); + } + this._loader.destroy(); + this._loader = null; + this._loaderClass = null; + this._dataSource = null; + this._stashBuffer = null; + this._stashUsed = this._stashSize = this._bufferSize = this._stashByteStart = 0; + this._currentRange = null; + this._speedSampler = null; + this._isEarlyEofReconnecting = false; + this._onDataArrival = null; + this._onSeeked = null; + this._onError = null; + this._onComplete = null; + this._onRedirect = null; + this._onRecoveredEarlyEof = null; + this._extraData = null; + } + }, { + key: 'isWorking', + value: function isWorking() { + return this._loader && this._loader.isWorking() && !this._paused; + } + }, { + key: 'isPaused', + value: function isPaused() { + return this._paused; + } + }, { + key: '_selectSeekHandler', + value: function _selectSeekHandler() { + var config = this._config; + if (config.seekType === 'range') { + this._seekHandler = new _rangeSeekHandler2.default(this._config.rangeLoadZeroStart); + } else if (config.seekType === 'param') { + var paramStart = config.seekParamStart || 'bstart'; + var paramEnd = config.seekParamEnd || 'bend'; + this._seekHandler = new _paramSeekHandler2.default(paramStart, paramEnd); + } else if (config.seekType === 'custom') { + if (typeof config.customSeekHandler !== 'function') { + throw new _exception.InvalidArgumentException('Custom seekType specified in config but invalid customSeekHandler!'); + } + this._seekHandler = new config.customSeekHandler(); + } else { + throw new _exception.InvalidArgumentException('Invalid seekType in config: ' + config.seekType); + } + } + }, { + key: '_selectLoader', + value: function _selectLoader() { + if (this._config.customLoader != null) { + this._loaderClass = this._config.customLoader; + } else if (this._isWebSocketURL) { + this._loaderClass = _websocketLoader2.default; + } else if (_fetchStreamLoader2.default.isSupported()) { + this._loaderClass = _fetchStreamLoader2.default; + } else if (_xhrMozChunkedLoader2.default.isSupported()) { + this._loaderClass = _xhrMozChunkedLoader2.default; + } else if (_xhrRangeLoader2.default.isSupported()) { + this._loaderClass = _xhrRangeLoader2.default; + } else { + throw new _exception.RuntimeException('Your browser doesn\'t support xhr with arraybuffer responseType!'); + } + } + }, { + key: '_createLoader', + value: function _createLoader() { + this._loader = new this._loaderClass(this._seekHandler, this._config); + if (this._loader.needStashBuffer === false) { + this._enableStash = false; + } + this._loader.onContentLengthKnown = this._onContentLengthKnown.bind(this); + this._loader.onURLRedirect = this._onURLRedirect.bind(this); + this._loader.onDataArrival = this._onLoaderChunkArrival.bind(this); + this._loader.onComplete = this._onLoaderComplete.bind(this); + this._loader.onError = this._onLoaderError.bind(this); + } + }, { + key: 'open', + value: function open(optionalFrom) { + this._currentRange = { + from: 0, + to: -1 + }; + if (optionalFrom) { + this._currentRange.from = optionalFrom; + } + this._speedSampler.reset(); + if (!optionalFrom) { + this._fullRequestFlag = true; + } + this._loader.open(this._dataSource, Object.assign({}, this._currentRange)); + } + }, { + key: 'abort', + value: function abort() { + this._loader.abort(); + if (this._paused) { + this._paused = false; + this._resumeFrom = 0; + } + } + }, { + key: 'pause', + value: function pause() { + if (this.isWorking()) { + this._loader.abort(); + if (this._stashUsed !== 0) { + this._resumeFrom = this._stashByteStart; + this._currentRange.to = this._stashByteStart - 1; + } else { + this._resumeFrom = this._currentRange.to + 1; + } + this._stashUsed = 0; + this._stashByteStart = 0; + this._paused = true; + } + } + }, { + key: 'resume', + value: function resume() { + if (this._paused) { + this._paused = false; + var bytes = this._resumeFrom; + this._resumeFrom = 0; + this._internalSeek(bytes, true); + } + } + }, { + key: 'seek', + value: function seek(bytes) { + this._paused = false; + this._stashUsed = 0; + this._stashByteStart = 0; + this._internalSeek(bytes, true); + } + }, { + key: '_internalSeek', + value: function _internalSeek(bytes, dropUnconsumed) { + if (this._loader.isWorking()) { + this._loader.abort(); + } + this._flushStashBuffer(dropUnconsumed); + this._loader.destroy(); + this._loader = null; + var requestRange = { + from: bytes, + to: -1 + }; + this._currentRange = { + from: requestRange.from, + to: -1 + }; + this._speedSampler.reset(); + this._stashSize = this._stashInitialSize; + this._createLoader(); + this._loader.open(this._dataSource, requestRange); + if (this._onSeeked) { + this._onSeeked(); + } + } + }, { + key: 'updateUrl', + value: function updateUrl(url) { + if (!url || typeof url !== 'string' || url.length === 0) { + throw new _exception.InvalidArgumentException('Url must be a non-empty string!'); + } + this._dataSource.url = url; + } + }, { + key: '_expandBuffer', + value: function _expandBuffer(expectedBytes) { + var bufferNewSize = this._stashSize; + while (bufferNewSize + 1024 * 1024 * 1 < expectedBytes) { + bufferNewSize *= 2; + } + bufferNewSize += 1024 * 1024 * 1; + if (bufferNewSize === this._bufferSize) { + return; + } + var newBuffer = new ArrayBuffer(bufferNewSize); + if (this._stashUsed > 0) { + var stashOldArray = new Uint8Array(this._stashBuffer, 0, this._stashUsed); + var stashNewArray = new Uint8Array(newBuffer, 0, bufferNewSize); + stashNewArray.set(stashOldArray, 0); + } + this._stashBuffer = newBuffer; + this._bufferSize = bufferNewSize; + } + }, { + key: '_normalizeSpeed', + value: function _normalizeSpeed(input) { + var list = this._speedNormalizeList; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (input < list[0]) { + return list[0]; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if (mid === last || input >= list[mid] && input < list[mid + 1]) { + return list[mid]; + } else if (list[mid] < input) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + } + }, { + key: '_adjustStashSize', + value: function _adjustStashSize(normalized) { + var stashSizeKB = 0; + if (this._config.isLive) { + stashSizeKB = normalized; + } else { + if (normalized < 512) { + stashSizeKB = normalized; + } else if (normalized >= 512 && normalized <= 1024) { + stashSizeKB = Math.floor(normalized * 1.5); + } else { + stashSizeKB = normalized * 2; + } + } + if (stashSizeKB > 8192) { + stashSizeKB = 8192; + } + var bufferSize = stashSizeKB * 1024 + 1024 * 1024 * 1; + if (this._bufferSize < bufferSize) { + this._expandBuffer(bufferSize); + } + this._stashSize = stashSizeKB * 1024; + } + }, { + key: '_dispatchChunks', + value: function _dispatchChunks(chunks, byteStart) { + this._currentRange.to = byteStart + chunks.byteLength - 1; + return this._onDataArrival(chunks, byteStart); + } + }, { + key: '_onURLRedirect', + value: function _onURLRedirect(redirectedURL) { + this._redirectedURL = redirectedURL; + if (this._onRedirect) { + this._onRedirect(redirectedURL); + } + } + }, { + key: '_onContentLengthKnown', + value: function _onContentLengthKnown(contentLength) { + if (contentLength && this._fullRequestFlag) { + this._totalLength = contentLength; + this._fullRequestFlag = false; + } + } + }, { + key: '_onLoaderChunkArrival', + value: function _onLoaderChunkArrival(chunk, byteStart, receivedLength) { + if (!this._onDataArrival) { + throw new _exception.IllegalStateException('IOController: No existing consumer (onDataArrival) callback!'); + } + if (this._paused) { + return; + } + if (this._isEarlyEofReconnecting) { + this._isEarlyEofReconnecting = false; + if (this._onRecoveredEarlyEof) { + this._onRecoveredEarlyEof(); + } + } + this._speedSampler.addBytes(chunk.byteLength); + var KBps = this._speedSampler.lastSecondKBps; + if (KBps !== 0) { + var normalized = this._normalizeSpeed(KBps); + if (this._speedNormalized !== normalized) { + this._speedNormalized = normalized; + this._adjustStashSize(normalized); + } + } + if (!this._enableStash) { + if (this._stashUsed === 0) { + var consumed = this._dispatchChunks(chunk, byteStart); + if (consumed < chunk.byteLength) { + var remain = chunk.byteLength - consumed; + if (remain > this._bufferSize) { + this._expandBuffer(remain); + } + var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + stashArray.set(new Uint8Array(chunk, consumed), 0); + this._stashUsed += remain; + this._stashByteStart = byteStart + consumed; + } + } else { + if (this._stashUsed + chunk.byteLength > this._bufferSize) { + this._expandBuffer(this._stashUsed + chunk.byteLength); + } + var _stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + _stashArray.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + var _consumed = this._dispatchChunks(this._stashBuffer.slice(0, this._stashUsed), this._stashByteStart); + if (_consumed < this._stashUsed && _consumed > 0) { + var remainArray = new Uint8Array(this._stashBuffer, _consumed); + _stashArray.set(remainArray, 0); + } + this._stashUsed -= _consumed; + this._stashByteStart += _consumed; + } + } else { + if (this._stashUsed === 0 && this._stashByteStart === 0) { + this._stashByteStart = byteStart; + } + if (this._stashUsed + chunk.byteLength <= this._stashSize) { + var _stashArray2 = new Uint8Array(this._stashBuffer, 0, this._stashSize); + _stashArray2.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + } else { + var _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + if (this._stashUsed > 0) { + var buffer = this._stashBuffer.slice(0, this._stashUsed); + var _consumed2 = this._dispatchChunks(buffer, this._stashByteStart); + if (_consumed2 < buffer.byteLength) { + if (_consumed2 > 0) { + var _remainArray = new Uint8Array(buffer, _consumed2); + _stashArray3.set(_remainArray, 0); + this._stashUsed = _remainArray.byteLength; + this._stashByteStart += _consumed2; + } + } else { + this._stashUsed = 0; + this._stashByteStart += _consumed2; + } + if (this._stashUsed + chunk.byteLength > this._bufferSize) { + this._expandBuffer(this._stashUsed + chunk.byteLength); + _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + } + _stashArray3.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + } else { + var _consumed3 = this._dispatchChunks(chunk, byteStart); + if (_consumed3 < chunk.byteLength) { + var _remain = chunk.byteLength - _consumed3; + if (_remain > this._bufferSize) { + this._expandBuffer(_remain); + _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + } + _stashArray3.set(new Uint8Array(chunk, _consumed3), 0); + this._stashUsed += _remain; + this._stashByteStart = byteStart + _consumed3; + } + } + } + } + } + }, { + key: '_flushStashBuffer', + value: function _flushStashBuffer(dropUnconsumed) { + if (this._stashUsed > 0) { + var buffer = this._stashBuffer.slice(0, this._stashUsed); + var consumed = this._dispatchChunks(buffer, this._stashByteStart); + var remain = buffer.byteLength - consumed; + if (consumed < buffer.byteLength) { + if (dropUnconsumed) { + _logger2.default.w(this.TAG, remain + ' bytes unconsumed data remain when flush buffer, dropped'); + } else { + if (consumed > 0) { + var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); + var remainArray = new Uint8Array(buffer, consumed); + stashArray.set(remainArray, 0); + this._stashUsed = remainArray.byteLength; + this._stashByteStart += consumed; + } + return 0; + } + } + this._stashUsed = 0; + this._stashByteStart = 0; + return remain; + } + return 0; + } + }, { + key: '_onLoaderComplete', + value: function _onLoaderComplete(from, to) { + this._flushStashBuffer(true); + if (this._onComplete) { + this._onComplete(this._extraData); + } + } + }, { + key: '_onLoaderError', + value: function _onLoaderError(type, data) { + _logger2.default.e(this.TAG, 'Loader error, code = ' + data.code + ', msg = ' + data.msg); + this._flushStashBuffer(false); + if (this._isEarlyEofReconnecting) { + this._isEarlyEofReconnecting = false; + type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF; + } + switch (type) { + case _loader.LoaderErrors.EARLY_EOF: { + if (!this._config.isLive) { + if (this._totalLength) { + var nextFrom = this._currentRange.to + 1; + if (nextFrom < this._totalLength) { + _logger2.default.w(this.TAG, 'Connection lost, trying reconnect...'); + this._isEarlyEofReconnecting = true; + this._internalSeek(nextFrom, false); + } + return; + } + } + type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF; + break; + } + case _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF: + case _loader.LoaderErrors.CONNECTING_TIMEOUT: + case _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID: + case _loader.LoaderErrors.EXCEPTION: + break; + } + if (this._onError) { + this._onError(type, data); + } else { + throw new _exception.RuntimeException('IOException: ' + data.msg); + } + } + }, { + key: 'status', + get: function get() { + return this._loader.status; + } + }, { + key: 'extraData', + get: function get() { + return this._extraData; + }, + set: function set(data) { + this._extraData = data; + } + }, { + key: 'onDataArrival', + get: function get() { + return this._onDataArrival; + }, + set: function set(callback) { + this._onDataArrival = callback; + } + }, { + key: 'onSeeked', + get: function get() { + return this._onSeeked; + }, + set: function set(callback) { + this._onSeeked = callback; + } + }, { + key: 'onError', + get: function get() { + return this._onError; + }, + set: function set(callback) { + this._onError = callback; + } + }, { + key: 'onComplete', + get: function get() { + return this._onComplete; + }, + set: function set(callback) { + this._onComplete = callback; + } + }, { + key: 'onRedirect', + get: function get() { + return this._onRedirect; + }, + set: function set(callback) { + this._onRedirect = callback; + } + }, { + key: 'onRecoveredEarlyEof', + get: function get() { + return this._onRecoveredEarlyEof; + }, + set: function set(callback) { + this._onRecoveredEarlyEof = callback; + } + }, { + key: 'currentURL', + get: function get() { + return this._dataSource.url; + } + }, { + key: 'hasRedirect', + get: function get() { + return this._redirectedURL != null || this._dataSource.redirectedURL != undefined; + } + }, { + key: 'currentRedirectedURL', + get: function get() { + return this._redirectedURL || this._dataSource.redirectedURL; + } + }, { + key: 'currentSpeed', + get: function get() { + if (this._loaderClass === _xhrRangeLoader2.default) { + return this._loader.currentSpeed; + } + return this._speedSampler.lastSecondKBps; + } + }, { + key: 'loaderType', + get: function get() { + return this._loader.type; + } + }]); + return IOController; + }(); + exports.default = IOController; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./fetch-stream-loader.js": 22, + "./loader.js": 24, + "./param-seek-handler.js": 25, + "./range-seek-handler.js": 26, + "./speed-sampler.js": 27, + "./websocket-loader.js": 28, + "./xhr-moz-chunked-loader.js": 29, + "./xhr-msstream-loader.js": 30, + "./xhr-range-loader.js": 31 + }], + 24: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.BaseLoader = exports.LoaderErrors = exports.LoaderStatus = undefined; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _exception = _dereq_('../utils/exception.js'); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var LoaderStatus = exports.LoaderStatus = { + kIdle: 0, + kConnecting: 1, + kBuffering: 2, + kError: 3, + kComplete: 4 + }; + var LoaderErrors = exports.LoaderErrors = { + OK: 'OK', + EXCEPTION: 'Exception', + HTTP_STATUS_CODE_INVALID: 'HttpStatusCodeInvalid', + CONNECTING_TIMEOUT: 'ConnectingTimeout', + EARLY_EOF: 'EarlyEof', + UNRECOVERABLE_EARLY_EOF: 'UnrecoverableEarlyEof' + }; + var BaseLoader = exports.BaseLoader = function() { + function BaseLoader(typeName) { + _classCallCheck(this, BaseLoader); + this._type = typeName || 'undefined'; + this._status = LoaderStatus.kIdle; + this._needStash = false; + this._onContentLengthKnown = null; + this._onURLRedirect = null; + this._onDataArrival = null; + this._onError = null; + this._onComplete = null; + } + _createClass(BaseLoader, [{ + key: 'destroy', + value: function destroy() { + this._status = LoaderStatus.kIdle; + this._onContentLengthKnown = null; + this._onURLRedirect = null; + this._onDataArrival = null; + this._onError = null; + this._onComplete = null; + } + }, { + key: 'isWorking', + value: function isWorking() { + return this._status === LoaderStatus.kConnecting || this._status === LoaderStatus.kBuffering; + } + }, { + key: 'open', + value: function open(dataSource, range) { + throw new _exception.NotImplementedException('Unimplemented abstract function!'); + } + }, { + key: 'abort', + value: function abort() { + throw new _exception.NotImplementedException('Unimplemented abstract function!'); + } + }, { + key: 'type', + get: function get() { + return this._type; + } + }, { + key: 'status', + get: function get() { + return this._status; + } + }, { + key: 'needStashBuffer', + get: function get() { + return this._needStash; + } + }, { + key: 'onContentLengthKnown', + get: function get() { + return this._onContentLengthKnown; + }, + set: function set(callback) { + this._onContentLengthKnown = callback; + } + }, { + key: 'onURLRedirect', + get: function get() { + return this._onURLRedirect; + }, + set: function set(callback) { + this._onURLRedirect = callback; + } + }, { + key: 'onDataArrival', + get: function get() { + return this._onDataArrival; + }, + set: function set(callback) { + this._onDataArrival = callback; + } + }, { + key: 'onError', + get: function get() { + return this._onError; + }, + set: function set(callback) { + this._onError = callback; + } + }, { + key: 'onComplete', + get: function get() { + return this._onComplete; + }, + set: function set(callback) { + this._onComplete = callback; + } + }]); + return BaseLoader; + }(); + }, { + "../utils/exception.js": 40 + }], + 25: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var ParamSeekHandler = function() { + function ParamSeekHandler(paramStart, paramEnd) { + _classCallCheck(this, ParamSeekHandler); + this._startName = paramStart; + this._endName = paramEnd; + } + _createClass(ParamSeekHandler, [{ + key: 'getConfig', + value: function getConfig(baseUrl, range) { + var url = baseUrl; + if (range.from !== 0 || range.to !== -1) { + var needAnd = true; + if (url.indexOf('?') === -1) { + url += '?'; + needAnd = false; + } + if (needAnd) { + url += '&'; + } + url += this._startName + '=' + range.from.toString(); + if (range.to !== -1) { + url += '&' + this._endName + '=' + range.to.toString(); + } + } + return { + url: url, + headers: {} + }; + } + }, { + key: 'removeURLParameters', + value: function removeURLParameters(seekedURL) { + var baseURL = seekedURL.split('?')[0]; + var params = undefined; + var queryIndex = seekedURL.indexOf('?'); + if (queryIndex !== -1) { + params = seekedURL.substring(queryIndex + 1); + } + var resultParams = ''; + if (params != undefined && params.length > 0) { + var pairs = params.split('&'); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split('='); + var requireAnd = i > 0; + if (pair[0] !== this._startName && pair[0] !== this._endName) { + if (requireAnd) { + resultParams += '&'; + } + resultParams += pairs[i]; + } + } + } + return resultParams.length === 0 ? baseURL : baseURL + '?' + resultParams; + } + }]); + return ParamSeekHandler; + }(); + exports.default = ParamSeekHandler; + }, {}], + 26: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var RangeSeekHandler = function() { + function RangeSeekHandler(zeroStart) { + _classCallCheck(this, RangeSeekHandler); + this._zeroStart = zeroStart || false; + } + _createClass(RangeSeekHandler, [{ + key: 'getConfig', + value: function getConfig(url, range) { + var headers = {}; + if (range.from !== 0 || range.to !== -1) { + var param = void 0; + if (range.to !== -1) { + param = 'bytes=' + range.from.toString() + '-' + range.to.toString(); + } else { + param = 'bytes=' + range.from.toString() + '-'; + } + headers['Range'] = param; + } else if (this._zeroStart) { + headers['Range'] = 'bytes=0-'; + } + return { + url: url, + headers: headers + }; + } + }, { + key: 'removeURLParameters', + value: function removeURLParameters(seekedURL) { + return seekedURL; + } + }]); + return RangeSeekHandler; + }(); + exports.default = RangeSeekHandler; + }, {}], + 27: [function(_dereq_, module, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var SpeedSampler = function() { + function SpeedSampler() { + _classCallCheck(this, SpeedSampler); + this._firstCheckpoint = 0; + this._lastCheckpoint = 0; + this._intervalBytes = 0; + this._totalBytes = 0; + this._lastSecondBytes = 0; + if (self.performance && self.performance.now) { + this._now = self.performance.now.bind(self.performance); + } else { + this._now = Date.now; + } + } + _createClass(SpeedSampler, [{ + key: "reset", + value: function reset() { + this._firstCheckpoint = this._lastCheckpoint = 0; + this._totalBytes = this._intervalBytes = 0; + this._lastSecondBytes = 0; + } + }, { + key: "addBytes", + value: function addBytes(bytes) { + if (this._firstCheckpoint === 0) { + this._firstCheckpoint = this._now(); + this._lastCheckpoint = this._firstCheckpoint; + this._intervalBytes += bytes; + this._totalBytes += bytes; + } else if (this._now() - this._lastCheckpoint < 1000) { + this._intervalBytes += bytes; + this._totalBytes += bytes; + } else { + this._lastSecondBytes = this._intervalBytes; + this._intervalBytes = bytes; + this._totalBytes += bytes; + this._lastCheckpoint = this._now(); + } + } + }, { + key: "currentKBps", + get: function get() { + this.addBytes(0); + var durationSeconds = (this._now() - this._lastCheckpoint) / 1000; + if (durationSeconds == 0) durationSeconds = 1; + return this._intervalBytes / durationSeconds / 1024; + } + }, { + key: "lastSecondKBps", + get: function get() { + this.addBytes(0); + if (this._lastSecondBytes !== 0) { + return this._lastSecondBytes / 1024; + } else { + if (this._now() - this._lastCheckpoint >= 500) { + return this.currentKBps; + } else { + return 0; + } + } + } + }, { + key: "averageKBps", + get: function get() { + var durationSeconds = (this._now() - this._firstCheckpoint) / 1000; + return this._totalBytes / durationSeconds / 1024; + } + }]); + return SpeedSampler; + }(); + exports.default = SpeedSampler; + }, {}], + 28: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _loader = _dereq_('./loader.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + var WebSocketLoader = function(_BaseLoader) { + _inherits(WebSocketLoader, _BaseLoader); + _createClass(WebSocketLoader, null, [{ + key: 'isSupported', + value: function isSupported() { + try { + return typeof self.WebSocket !== 'undefined'; + } catch (e) { + return false; + } + } + }]); + + function WebSocketLoader() { + _classCallCheck(this, WebSocketLoader); + var _this = _possibleConstructorReturn(this, (WebSocketLoader.__proto__ || Object.getPrototypeOf(WebSocketLoader)).call(this, 'websocket-loader')); + _this.TAG = 'WebSocketLoader'; + _this._needStash = true; + _this._ws = null; + _this._requestAbort = false; + _this._receivedLength = 0; + return _this; + } + _createClass(WebSocketLoader, [{ + key: 'destroy', + value: function destroy() { + if (this._ws) { + this.abort(); + } + _get(WebSocketLoader.prototype.__proto__ || Object.getPrototypeOf(WebSocketLoader.prototype), 'destroy', this).call(this); + } + }, { + key: 'open', + value: function open(dataSource) { + try { + var ws = this._ws = new self.WebSocket(dataSource.url); + ws.binaryType = 'arraybuffer'; + ws.onopen = this._onWebSocketOpen.bind(this); + ws.onclose = this._onWebSocketClose.bind(this); + ws.onmessage = this._onWebSocketMessage.bind(this); + ws.onerror = this._onWebSocketError.bind(this); + this._status = _loader.LoaderStatus.kConnecting; + } catch (e) { + this._status = _loader.LoaderStatus.kError; + var info = { + code: e.code, + msg: e.message + }; + if (this._onError) { + this._onError(_loader.LoaderErrors.EXCEPTION, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + } + }, { + key: 'abort', + value: function abort() { + var ws = this._ws; + if (ws && (ws.readyState === 0 || ws.readyState === 1)) { + this._requestAbort = true; + ws.close(); + } + this._ws = null; + this._status = _loader.LoaderStatus.kComplete; + } + }, { + key: '_onWebSocketOpen', + value: function _onWebSocketOpen(e) { + this._status = _loader.LoaderStatus.kBuffering; + } + }, { + key: '_onWebSocketClose', + value: function _onWebSocketClose(e) { + if (this._requestAbort === true) { + this._requestAbort = false; + return; + } + this._status = _loader.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete(0, this._receivedLength - 1); + } + } + }, { + key: '_onWebSocketMessage', + value: function _onWebSocketMessage(e) { + var _this2 = this; + if (e.data instanceof ArrayBuffer) { + this._dispatchArrayBuffer(e.data); + } else if (e.data instanceof Blob) { + var reader = new FileReader(); + reader.onload = function() { + _this2._dispatchArrayBuffer(reader.result); + }; + reader.readAsArrayBuffer(e.data); + } else { + this._status = _loader.LoaderStatus.kError; + var info = { + code: -1, + msg: 'Unsupported WebSocket message type: ' + e.data.constructor.name + }; + if (this._onError) { + this._onError(_loader.LoaderErrors.EXCEPTION, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + } + }, { + key: '_dispatchArrayBuffer', + value: function _dispatchArrayBuffer(arraybuffer) { + var chunk = arraybuffer; + var byteStart = this._receivedLength; + this._receivedLength += chunk.byteLength; + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + } + }, { + key: '_onWebSocketError', + value: function _onWebSocketError(e) { + this._status = _loader.LoaderStatus.kError; + var info = { + code: e.code, + msg: e.message + }; + if (this._onError) { + this._onError(_loader.LoaderErrors.EXCEPTION, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + }]); + return WebSocketLoader; + }(_loader.BaseLoader); + exports.default = WebSocketLoader; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./loader.js": 24 + }], + 29: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _loader = _dereq_('./loader.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + var MozChunkedLoader = function(_BaseLoader) { + _inherits(MozChunkedLoader, _BaseLoader); + _createClass(MozChunkedLoader, null, [{ + key: 'isSupported', + value: function isSupported() { + try { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://example.com', true); + xhr.responseType = 'moz-chunked-arraybuffer'; + return xhr.responseType === 'moz-chunked-arraybuffer'; + } catch (e) { + _logger2.default.w('MozChunkedLoader', e.message); + return false; + } + } + }]); + + function MozChunkedLoader(seekHandler, config) { + _classCallCheck(this, MozChunkedLoader); + var _this = _possibleConstructorReturn(this, (MozChunkedLoader.__proto__ || Object.getPrototypeOf(MozChunkedLoader)).call(this, 'xhr-moz-chunked-loader')); + _this.TAG = 'MozChunkedLoader'; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = true; + _this._xhr = null; + _this._requestAbort = false; + _this._contentLength = null; + _this._receivedLength = 0; + return _this; + } + _createClass(MozChunkedLoader, [{ + key: 'destroy', + value: function destroy() { + if (this.isWorking()) { + this.abort(); + } + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onloadend = null; + this._xhr.onerror = null; + this._xhr = null; + } + _get(MozChunkedLoader.prototype.__proto__ || Object.getPrototypeOf(MozChunkedLoader.prototype), 'destroy', this).call(this); + } + }, { + key: 'open', + value: function open(dataSource, range) { + this._dataSource = dataSource; + this._range = range; + var sourceURL = dataSource.url; + if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) { + sourceURL = dataSource.redirectedURL; + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + this._requestURL = seekConfig.url; + var xhr = this._xhr = new XMLHttpRequest(); + xhr.open('GET', seekConfig.url, true); + xhr.responseType = 'moz-chunked-arraybuffer'; + xhr.onreadystatechange = this._onReadyStateChange.bind(this); + xhr.onprogress = this._onProgress.bind(this); + xhr.onloadend = this._onLoadEnd.bind(this); + xhr.onerror = this._onXhrError.bind(this); + if (dataSource.withCredentials) { + xhr.withCredentials = true; + } + if (_typeof(seekConfig.headers) === 'object') { + var headers = seekConfig.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + if (_typeof(this._config.headers) === 'object') { + var _headers = this._config.headers; + for (var _key in _headers) { + if (_headers.hasOwnProperty(_key)) { + xhr.setRequestHeader(_key, _headers[_key]); + } + } + } + this._status = _loader.LoaderStatus.kConnecting; + xhr.send(); + } + }, { + key: 'abort', + value: function abort() { + this._requestAbort = true; + if (this._xhr) { + this._xhr.abort(); + } + this._status = _loader.LoaderStatus.kComplete; + } + }, { + key: '_onReadyStateChange', + value: function _onReadyStateChange(e) { + var xhr = e.target; + if (xhr.readyState === 2) { + if (xhr.responseURL != undefined && xhr.responseURL !== this._requestURL) { + if (this._onURLRedirect) { + var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); + this._onURLRedirect(redirectedURL); + } + } + if (xhr.status !== 0 && (xhr.status < 200 || xhr.status > 299)) { + this._status = _loader.LoaderStatus.kError; + if (this._onError) { + this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { + code: xhr.status, + msg: xhr.statusText + }); + } else { + throw new _exception.RuntimeException('MozChunkedLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); + } + } else { + this._status = _loader.LoaderStatus.kBuffering; + } + } + } + }, { + key: '_onProgress', + value: function _onProgress(e) { + if (this._status === _loader.LoaderStatus.kError) { + return; + } + if (this._contentLength === null) { + if (e.total !== null && e.total !== 0) { + this._contentLength = e.total; + if (this._onContentLengthKnown) { + this._onContentLengthKnown(this._contentLength); + } + } + } + var chunk = e.target.response; + var byteStart = this._range.from + this._receivedLength; + this._receivedLength += chunk.byteLength; + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + } + }, { + key: '_onLoadEnd', + value: function _onLoadEnd(e) { + if (this._requestAbort === true) { + this._requestAbort = false; + return; + } else if (this._status === _loader.LoaderStatus.kError) { + return; + } + this._status = _loader.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete(this._range.from, this._range.from + this._receivedLength - 1); + } + } + }, { + key: '_onXhrError', + value: function _onXhrError(e) { + this._status = _loader.LoaderStatus.kError; + var type = 0; + var info = null; + if (this._contentLength && e.loaded < this._contentLength) { + type = _loader.LoaderErrors.EARLY_EOF; + info = { + code: -1, + msg: 'Moz-Chunked stream meet Early-Eof' + }; + } else { + type = _loader.LoaderErrors.EXCEPTION; + info = { + code: -1, + msg: e.constructor.name + ' ' + e.type + }; + } + if (this._onError) { + this._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + }]); + return MozChunkedLoader; + }(_loader.BaseLoader); + exports.default = MozChunkedLoader; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./loader.js": 24 + }], + 30: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _loader = _dereq_('./loader.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + var MSStreamLoader = function(_BaseLoader) { + _inherits(MSStreamLoader, _BaseLoader); + _createClass(MSStreamLoader, null, [{ + key: 'isSupported', + value: function isSupported() { + try { + if (typeof self.MSStream === 'undefined' || typeof self.MSStreamReader === 'undefined') { + return false; + } + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://example.com', true); + xhr.responseType = 'ms-stream'; + return xhr.responseType === 'ms-stream'; + } catch (e) { + _logger2.default.w('MSStreamLoader', e.message); + return false; + } + } + }]); + + function MSStreamLoader(seekHandler, config) { + _classCallCheck(this, MSStreamLoader); + var _this = _possibleConstructorReturn(this, (MSStreamLoader.__proto__ || Object.getPrototypeOf(MSStreamLoader)).call(this, 'xhr-msstream-loader')); + _this.TAG = 'MSStreamLoader'; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = true; + _this._xhr = null; + _this._reader = null; + _this._totalRange = null; + _this._currentRange = null; + _this._currentRequestURL = null; + _this._currentRedirectedURL = null; + _this._contentLength = null; + _this._receivedLength = 0; + _this._bufferLimit = 16 * 1024 * 1024; + _this._lastTimeBufferSize = 0; + _this._isReconnecting = false; + return _this; + } + _createClass(MSStreamLoader, [{ + key: 'destroy', + value: function destroy() { + if (this.isWorking()) { + this.abort(); + } + if (this._reader) { + this._reader.onprogress = null; + this._reader.onload = null; + this._reader.onerror = null; + this._reader = null; + } + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr = null; + } + _get(MSStreamLoader.prototype.__proto__ || Object.getPrototypeOf(MSStreamLoader.prototype), 'destroy', this).call(this); + } + }, { + key: 'open', + value: function open(dataSource, range) { + this._internalOpen(dataSource, range, false); + } + }, { + key: '_internalOpen', + value: function _internalOpen(dataSource, range, isSubrange) { + this._dataSource = dataSource; + if (!isSubrange) { + this._totalRange = range; + } else { + this._currentRange = range; + } + var sourceURL = dataSource.url; + if (this._config.reuseRedirectedURL) { + if (this._currentRedirectedURL != undefined) { + sourceURL = this._currentRedirectedURL; + } else if (dataSource.redirectedURL != undefined) { + sourceURL = dataSource.redirectedURL; + } + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + this._currentRequestURL = seekConfig.url; + var reader = this._reader = new self.MSStreamReader(); + reader.onprogress = this._msrOnProgress.bind(this); + reader.onload = this._msrOnLoad.bind(this); + reader.onerror = this._msrOnError.bind(this); + var xhr = this._xhr = new XMLHttpRequest(); + xhr.open('GET', seekConfig.url, true); + xhr.responseType = 'ms-stream'; + xhr.onreadystatechange = this._xhrOnReadyStateChange.bind(this); + xhr.onerror = this._xhrOnError.bind(this); + if (dataSource.withCredentials) { + xhr.withCredentials = true; + } + if (_typeof(seekConfig.headers) === 'object') { + var headers = seekConfig.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + if (_typeof(this._config.headers) === 'object') { + var _headers = this._config.headers; + for (var _key in _headers) { + if (_headers.hasOwnProperty(_key)) { + xhr.setRequestHeader(_key, _headers[_key]); + } + } + } + if (this._isReconnecting) { + this._isReconnecting = false; + } else { + this._status = _loader.LoaderStatus.kConnecting; + } + xhr.send(); + } + }, { + key: 'abort', + value: function abort() { + this._internalAbort(); + this._status = _loader.LoaderStatus.kComplete; + } + }, { + key: '_internalAbort', + value: function _internalAbort() { + if (this._reader) { + if (this._reader.readyState === 1) { + this._reader.abort(); + } + this._reader.onprogress = null; + this._reader.onload = null; + this._reader.onerror = null; + this._reader = null; + } + if (this._xhr) { + this._xhr.abort(); + this._xhr.onreadystatechange = null; + this._xhr = null; + } + } + }, { + key: '_xhrOnReadyStateChange', + value: function _xhrOnReadyStateChange(e) { + var xhr = e.target; + if (xhr.readyState === 2) { + if (xhr.status >= 200 && xhr.status <= 299) { + this._status = _loader.LoaderStatus.kBuffering; + if (xhr.responseURL != undefined) { + var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); + if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) { + this._currentRedirectedURL = redirectedURL; + if (this._onURLRedirect) { + this._onURLRedirect(redirectedURL); + } + } + } + var lengthHeader = xhr.getResponseHeader('Content-Length'); + if (lengthHeader != null && this._contentLength == null) { + var length = parseInt(lengthHeader); + if (length > 0) { + this._contentLength = length; + if (this._onContentLengthKnown) { + this._onContentLengthKnown(this._contentLength); + } + } + } + } else { + this._status = _loader.LoaderStatus.kError; + if (this._onError) { + this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { + code: xhr.status, + msg: xhr.statusText + }); + } else { + throw new _exception.RuntimeException('MSStreamLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); + } + } + } else if (xhr.readyState === 3) { + if (xhr.status >= 200 && xhr.status <= 299) { + this._status = _loader.LoaderStatus.kBuffering; + var msstream = xhr.response; + this._reader.readAsArrayBuffer(msstream); + } + } + } + }, { + key: '_xhrOnError', + value: function _xhrOnError(e) { + this._status = _loader.LoaderStatus.kError; + var type = _loader.LoaderErrors.EXCEPTION; + var info = { + code: -1, + msg: e.constructor.name + ' ' + e.type + }; + if (this._onError) { + this._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + }, { + key: '_msrOnProgress', + value: function _msrOnProgress(e) { + var reader = e.target; + var bigbuffer = reader.result; + if (bigbuffer == null) { + this._doReconnectIfNeeded(); + return; + } + var slice = bigbuffer.slice(this._lastTimeBufferSize); + this._lastTimeBufferSize = bigbuffer.byteLength; + var byteStart = this._totalRange.from + this._receivedLength; + this._receivedLength += slice.byteLength; + if (this._onDataArrival) { + this._onDataArrival(slice, byteStart, this._receivedLength); + } + if (bigbuffer.byteLength >= this._bufferLimit) { + _logger2.default.v(this.TAG, 'MSStream buffer exceeded max size near ' + (byteStart + slice.byteLength) + ', reconnecting...'); + this._doReconnectIfNeeded(); + } + } + }, { + key: '_doReconnectIfNeeded', + value: function _doReconnectIfNeeded() { + if (this._contentLength == null || this._receivedLength < this._contentLength) { + this._isReconnecting = true; + this._lastTimeBufferSize = 0; + this._internalAbort(); + var range = { + from: this._totalRange.from + this._receivedLength, + to: -1 + }; + this._internalOpen(this._dataSource, range, true); + } + } + }, { + key: '_msrOnLoad', + value: function _msrOnLoad(e) { + this._status = _loader.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete(this._totalRange.from, this._totalRange.from + this._receivedLength - 1); + } + } + }, { + key: '_msrOnError', + value: function _msrOnError(e) { + this._status = _loader.LoaderStatus.kError; + var type = 0; + var info = null; + if (this._contentLength && this._receivedLength < this._contentLength) { + type = _loader.LoaderErrors.EARLY_EOF; + info = { + code: -1, + msg: 'MSStream meet Early-Eof' + }; + } else { + type = _loader.LoaderErrors.EARLY_EOF; + info = { + code: -1, + msg: e.constructor.name + ' ' + e.type + }; + } + if (this._onError) { + this._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + }]); + return MSStreamLoader; + }(_loader.BaseLoader); + exports.default = MSStreamLoader; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./loader.js": 24 + }], + 31: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _speedSampler = _dereq_('./speed-sampler.js'); + var _speedSampler2 = _interopRequireDefault(_speedSampler); + var _loader = _dereq_('./loader.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + var RangeLoader = function(_BaseLoader) { + _inherits(RangeLoader, _BaseLoader); + _createClass(RangeLoader, null, [{ + key: 'isSupported', + value: function isSupported() { + try { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://example.com', true); + xhr.responseType = 'arraybuffer'; + return xhr.responseType === 'arraybuffer'; + } catch (e) { + _logger2.default.w('RangeLoader', e.message); + return false; + } + } + }]); + + function RangeLoader(seekHandler, config) { + _classCallCheck(this, RangeLoader); + var _this = _possibleConstructorReturn(this, (RangeLoader.__proto__ || Object.getPrototypeOf(RangeLoader)).call(this, 'xhr-range-loader')); + _this.TAG = 'RangeLoader'; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = false; + _this._chunkSizeKBList = [128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 5120, 6144, 7168, 8192]; + _this._currentChunkSizeKB = 384; + _this._currentSpeedNormalized = 0; + _this._zeroSpeedChunkCount = 0; + _this._xhr = null; + _this._speedSampler = new _speedSampler2.default(); + _this._requestAbort = false; + _this._waitForTotalLength = false; + _this._totalLengthReceived = false; + _this._currentRequestURL = null; + _this._currentRedirectedURL = null; + _this._currentRequestRange = null; + _this._totalLength = null; + _this._contentLength = null; + _this._receivedLength = 0; + _this._lastTimeLoaded = 0; + return _this; + } + _createClass(RangeLoader, [{ + key: 'destroy', + value: function destroy() { + if (this.isWorking()) { + this.abort(); + } + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onload = null; + this._xhr.onerror = null; + this._xhr = null; + } + _get(RangeLoader.prototype.__proto__ || Object.getPrototypeOf(RangeLoader.prototype), 'destroy', this).call(this); + } + }, { + key: 'open', + value: function open(dataSource, range) { + this._dataSource = dataSource; + this._range = range; + this._status = _loader.LoaderStatus.kConnecting; + var useRefTotalLength = false; + if (this._dataSource.filesize != undefined && this._dataSource.filesize !== 0) { + useRefTotalLength = true; + this._totalLength = this._dataSource.filesize; + } + if (!this._totalLengthReceived && !useRefTotalLength) { + this._waitForTotalLength = true; + this._internalOpen(this._dataSource, { + from: 0, + to: -1 + }); + } else { + this._openSubRange(); + } + } + }, { + key: '_openSubRange', + value: function _openSubRange() { + var chunkSize = this._currentChunkSizeKB * 1024; + var from = this._range.from + this._receivedLength; + var to = from + chunkSize; + if (this._contentLength != null) { + if (to - this._range.from >= this._contentLength) { + to = this._range.from + this._contentLength - 1; + } + } + this._currentRequestRange = { + from: from, + to: to + }; + this._internalOpen(this._dataSource, this._currentRequestRange); + } + }, { + key: '_internalOpen', + value: function _internalOpen(dataSource, range) { + this._lastTimeLoaded = 0; + var sourceURL = dataSource.url; + if (this._config.reuseRedirectedURL) { + if (this._currentRedirectedURL != undefined) { + sourceURL = this._currentRedirectedURL; + } else if (dataSource.redirectedURL != undefined) { + sourceURL = dataSource.redirectedURL; + } + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + this._currentRequestURL = seekConfig.url; + var xhr = this._xhr = new XMLHttpRequest(); + xhr.open('GET', seekConfig.url, true); + xhr.responseType = 'arraybuffer'; + xhr.onreadystatechange = this._onReadyStateChange.bind(this); + xhr.onprogress = this._onProgress.bind(this); + xhr.onload = this._onLoad.bind(this); + xhr.onerror = this._onXhrError.bind(this); + if (dataSource.withCredentials) { + xhr.withCredentials = true; + } + if (_typeof(seekConfig.headers) === 'object') { + var headers = seekConfig.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + if (_typeof(this._config.headers) === 'object') { + var _headers = this._config.headers; + for (var _key in _headers) { + if (_headers.hasOwnProperty(_key)) { + xhr.setRequestHeader(_key, _headers[_key]); + } + } + } + xhr.send(); + } + }, { + key: 'abort', + value: function abort() { + this._requestAbort = true; + this._internalAbort(); + this._status = _loader.LoaderStatus.kComplete; + } + }, { + key: '_internalAbort', + value: function _internalAbort() { + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onload = null; + this._xhr.onerror = null; + this._xhr.abort(); + this._xhr = null; + } + } + }, { + key: '_onReadyStateChange', + value: function _onReadyStateChange(e) { + var xhr = e.target; + if (xhr.readyState === 2) { + if (xhr.responseURL != undefined) { + var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); + if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) { + this._currentRedirectedURL = redirectedURL; + if (this._onURLRedirect) { + this._onURLRedirect(redirectedURL); + } + } + } + if (xhr.status >= 200 && xhr.status <= 299) { + if (this._waitForTotalLength) { + return; + } + this._status = _loader.LoaderStatus.kBuffering; + } else { + this._status = _loader.LoaderStatus.kError; + if (this._onError) { + this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { + code: xhr.status, + msg: xhr.statusText + }); + } else { + throw new _exception.RuntimeException('RangeLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); + } + } + } + } + }, { + key: '_onProgress', + value: function _onProgress(e) { + if (this._status === _loader.LoaderStatus.kError) { + return; + } + if (this._contentLength === null) { + var openNextRange = false; + if (this._waitForTotalLength) { + this._waitForTotalLength = false; + this._totalLengthReceived = true; + openNextRange = true; + var total = e.total; + this._internalAbort(); + if (total != null & total !== 0) { + this._totalLength = total; + } + } + if (this._range.to === -1) { + this._contentLength = this._totalLength - this._range.from; + } else { + this._contentLength = this._range.to - this._range.from + 1; + } + if (openNextRange) { + this._openSubRange(); + return; + } + if (this._onContentLengthKnown) { + this._onContentLengthKnown(this._contentLength); + } + } + var delta = e.loaded - this._lastTimeLoaded; + this._lastTimeLoaded = e.loaded; + this._speedSampler.addBytes(delta); + } + }, { + key: '_normalizeSpeed', + value: function _normalizeSpeed(input) { + var list = this._chunkSizeKBList; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (input < list[0]) { + return list[0]; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if (mid === last || input >= list[mid] && input < list[mid + 1]) { + return list[mid]; + } else if (list[mid] < input) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + } + }, { + key: '_onLoad', + value: function _onLoad(e) { + if (this._status === _loader.LoaderStatus.kError) { + return; + } + if (this._waitForTotalLength) { + this._waitForTotalLength = false; + return; + } + this._lastTimeLoaded = 0; + var KBps = this._speedSampler.lastSecondKBps; + if (KBps === 0) { + this._zeroSpeedChunkCount++; + if (this._zeroSpeedChunkCount >= 3) { + KBps = this._speedSampler.currentKBps; + } + } + if (KBps !== 0) { + var normalized = this._normalizeSpeed(KBps); + if (this._currentSpeedNormalized !== normalized) { + this._currentSpeedNormalized = normalized; + this._currentChunkSizeKB = normalized; + } + } + var chunk = e.target.response; + var byteStart = this._range.from + this._receivedLength; + this._receivedLength += chunk.byteLength; + var reportComplete = false; + if (this._contentLength != null && this._receivedLength < this._contentLength) { + this._openSubRange(); + } else { + reportComplete = true; + } + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + if (reportComplete) { + this._status = _loader.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete(this._range.from, this._range.from + this._receivedLength - 1); + } + } + } + }, { + key: '_onXhrError', + value: function _onXhrError(e) { + this._status = _loader.LoaderStatus.kError; + var type = 0; + var info = null; + if (this._contentLength && this._receivedLength > 0 && this._receivedLength < this._contentLength) { + type = _loader.LoaderErrors.EARLY_EOF; + info = { + code: -1, + msg: 'RangeLoader meet Early-Eof' + }; + } else { + type = _loader.LoaderErrors.EXCEPTION; + info = { + code: -1, + msg: e.constructor.name + ' ' + e.type + }; + } + if (this._onError) { + this._onError(type, info); + } else { + throw new _exception.RuntimeException(info.msg); + } + } + }, { + key: 'currentSpeed', + get: function get() { + return this._speedSampler.lastSecondKBps; + } + }]); + return RangeLoader; + }(_loader.BaseLoader); + exports.default = RangeLoader; + }, { + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./loader.js": 24, + "./speed-sampler.js": 27 + }], + 32: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _browser = _dereq_('../utils/browser.js'); + var _browser2 = _interopRequireDefault(_browser); + var _playerEvents = _dereq_('./player-events.js'); + var _playerEvents2 = _interopRequireDefault(_playerEvents); + var _transmuxer = _dereq_('../core/transmuxer.js'); + var _transmuxer2 = _interopRequireDefault(_transmuxer); + var _transmuxingEvents = _dereq_('../core/transmuxing-events.js'); + var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); + var _mseController = _dereq_('../core/mse-controller.js'); + var _mseController2 = _interopRequireDefault(_mseController); + var _mseEvents = _dereq_('../core/mse-events.js'); + var _mseEvents2 = _interopRequireDefault(_mseEvents); + var _playerErrors = _dereq_('./player-errors.js'); + var _config = _dereq_('../config.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var FlvPlayer = function() { + function FlvPlayer(mediaDataSource, config) { + _classCallCheck(this, FlvPlayer); + this.TAG = 'FlvPlayer'; + this._type = 'FlvPlayer'; + this._emitter = new _events2.default(); + this._config = (0, _config.createDefaultConfig)(); + if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') { + Object.assign(this._config, config); + } + if (mediaDataSource.type.toLowerCase() !== 'flv') { + throw new _exception.InvalidArgumentException('FlvPlayer requires an flv MediaDataSource input!'); + } + if (mediaDataSource.isLive === true) { + this._config.isLive = true; + } + this.e = { + onvLoadedMetadata: this._onvLoadedMetadata.bind(this), + onvSeeking: this._onvSeeking.bind(this), + onvCanPlay: this._onvCanPlay.bind(this), + onvStalled: this._onvStalled.bind(this), + onvProgress: this._onvProgress.bind(this) + }; + if (self.performance && self.performance.now) { + this._now = self.performance.now.bind(self.performance); + } else { + this._now = Date.now; + } + this._pendingSeekTime = null; + this._requestSetTime = false; + this._seekpointRecord = null; + this._progressChecker = null; + this._mediaDataSource = mediaDataSource; + this._mediaElement = null; + this._msectl = null; + this._transmuxer = null; + this._mseSourceOpened = false; + this._hasPendingLoad = false; + this._receivedCanPlay = false; + this._mediaInfo = null; + this._statisticsInfo = null; + var chromeNeedIDRFix = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661); + this._alwaysSeekKeyframe = chromeNeedIDRFix || _browser2.default.msedge || _browser2.default.msie ? true : false; + if (this._alwaysSeekKeyframe) { + this._config.accurateSeek = false; + } + } + _createClass(FlvPlayer, [{ + key: 'destroy', + value: function destroy() { + if (this._progressChecker != null) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + } + if (this._transmuxer) { + this.unload(); + } + if (this._mediaElement) { + this.detachMediaElement(); + } + this.e = null; + this._mediaDataSource = null; + this._emitter.removeAllListeners(); + this._emitter = null; + } + }, { + key: 'on', + value: function on(event, listener) { + var _this = this; + if (event === _playerEvents2.default.MEDIA_INFO) { + if (this._mediaInfo != null) { + Promise.resolve().then(function() { + _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo); + }); + } + } else if (event === _playerEvents2.default.STATISTICS_INFO) { + if (this._statisticsInfo != null) { + Promise.resolve().then(function() { + _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo); + }); + } + } + this._emitter.addListener(event, listener); + } + }, { + key: 'off', + value: function off(event, listener) { + this._emitter.removeListener(event, listener); + } + }, { + key: 'attachMediaElement', + value: function attachMediaElement(mediaElement) { + var _this2 = this; + this._mediaElement = mediaElement; + mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata); + mediaElement.addEventListener('seeking', this.e.onvSeeking); + mediaElement.addEventListener('canplay', this.e.onvCanPlay); + mediaElement.addEventListener('stalled', this.e.onvStalled); + mediaElement.addEventListener('progress', this.e.onvProgress); + this._msectl = new _mseController2.default(this._config); + this._msectl.on(_mseEvents2.default.UPDATE_END, this._onmseUpdateEnd.bind(this)); + this._msectl.on(_mseEvents2.default.BUFFER_FULL, this._onmseBufferFull.bind(this)); + this._msectl.on(_mseEvents2.default.SOURCE_OPEN, function() { + _this2._mseSourceOpened = true; + if (_this2._hasPendingLoad) { + _this2._hasPendingLoad = false; + _this2.load(); + } + }); + this._msectl.on(_mseEvents2.default.ERROR, function(info) { + _this2._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, _playerErrors.ErrorDetails.MEDIA_MSE_ERROR, info); + }); + this._msectl.attachMediaElement(mediaElement); + if (this._pendingSeekTime != null) { + try { + mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } catch (e) {} + } + } + }, { + key: 'detachMediaElement', + value: function detachMediaElement() { + if (this._mediaElement) { + this._msectl.detachMediaElement(); + this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata); + this._mediaElement.removeEventListener('seeking', this.e.onvSeeking); + this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay); + this._mediaElement.removeEventListener('stalled', this.e.onvStalled); + this._mediaElement.removeEventListener('progress', this.e.onvProgress); + this._mediaElement = null; + } + if (this._msectl) { + this._msectl.destroy(); + this._msectl = null; + } + } + }, { + key: 'load', + value: function load() { + var _this3 = this; + if (!this._mediaElement) { + throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!'); + } + if (this._transmuxer) { + throw new _exception.IllegalStateException('FlvPlayer.load() has been called, please call unload() first!'); + } + if (this._hasPendingLoad) { + return; + } + if (this._config.deferLoadAfterSourceOpen && this._mseSourceOpened === false) { + this._hasPendingLoad = true; + return; + } + if (this._mediaElement.readyState > 0) { + this._requestSetTime = true; + this._mediaElement.currentTime = 0; + } + this._transmuxer = new _transmuxer2.default(this._mediaDataSource, this._config); + this._transmuxer.on(_transmuxingEvents2.default.INIT_SEGMENT, function(type, is) { + _this3._msectl.appendInitSegment(is); + }); + this._transmuxer.on(_transmuxingEvents2.default.MEDIA_SEGMENT, function(type, ms) { + _this3._msectl.appendMediaSegment(ms); + if (_this3._config.lazyLoad && !_this3._config.isLive) { + var currentTime = _this3._mediaElement.currentTime; + if (ms.info.endDts >= (currentTime + _this3._config.lazyLoadMaxDuration) * 1000) { + if (_this3._progressChecker == null) { + _logger2.default.v(_this3.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task'); + _this3._suspendTransmuxer(); + } + } + } + }); + this._transmuxer.on(_transmuxingEvents2.default.LOADING_COMPLETE, function() { + _this3._msectl.endOfStream(); + _this3._emitter.emit(_playerEvents2.default.LOADING_COMPLETE); + }); + this._transmuxer.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, function() { + _this3._emitter.emit(_playerEvents2.default.RECOVERED_EARLY_EOF); + }); + this._transmuxer.on(_transmuxingEvents2.default.IO_ERROR, function(detail, info) { + _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.NETWORK_ERROR, detail, info); + }); + this._transmuxer.on(_transmuxingEvents2.default.DEMUX_ERROR, function(detail, info) { + _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, detail, { + code: -1, + msg: info + }); + }); + this._transmuxer.on(_transmuxingEvents2.default.MEDIA_INFO, function(mediaInfo) { + _this3._mediaInfo = mediaInfo; + _this3._emitter.emit(_playerEvents2.default.MEDIA_INFO, Object.assign({}, mediaInfo)); + }); + this._transmuxer.on(_transmuxingEvents2.default.METADATA_ARRIVED, function(metadata) { + _this3._emitter.emit(_playerEvents2.default.METADATA_ARRIVED, metadata); + }); + this._transmuxer.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, function(data) { + _this3._emitter.emit(_playerEvents2.default.SCRIPTDATA_ARRIVED, data); + }); + this._transmuxer.on(_transmuxingEvents2.default.STATISTICS_INFO, function(statInfo) { + _this3._statisticsInfo = _this3._fillStatisticsInfo(statInfo); + _this3._emitter.emit(_playerEvents2.default.STATISTICS_INFO, Object.assign({}, _this3._statisticsInfo)); + }); + this._transmuxer.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, function(milliseconds) { + if (_this3._mediaElement && !_this3._config.accurateSeek) { + _this3._requestSetTime = true; + _this3._mediaElement.currentTime = milliseconds / 1000; + } + }); + this._transmuxer.open(); + } + }, { + key: 'unload', + value: function unload() { + if (this._mediaElement) { + this._mediaElement.pause(); + } + if (this._msectl) { + this._msectl.seek(0); + } + if (this._transmuxer) { + this._transmuxer.close(); + this._transmuxer.destroy(); + this._transmuxer = null; + } + } + }, { + key: 'play', + value: function play() { + return this._mediaElement.play(); + } + }, { + key: 'pause', + value: function pause() { + this._mediaElement.pause(); + } + }, { + key: '_fillStatisticsInfo', + value: function _fillStatisticsInfo(statInfo) { + statInfo.playerType = this._type; + if (!(this._mediaElement instanceof HTMLVideoElement)) { + return statInfo; + } + var hasQualityInfo = true; + var decoded = 0; + var dropped = 0; + if (this._mediaElement.getVideoPlaybackQuality) { + var quality = this._mediaElement.getVideoPlaybackQuality(); + decoded = quality.totalVideoFrames; + dropped = quality.droppedVideoFrames; + } else if (this._mediaElement.webkitDecodedFrameCount != undefined) { + decoded = this._mediaElement.webkitDecodedFrameCount; + dropped = this._mediaElement.webkitDroppedFrameCount; + } else { + hasQualityInfo = false; + } + if (hasQualityInfo) { + statInfo.decodedFrames = decoded; + statInfo.droppedFrames = dropped; + } + return statInfo; + } + }, { + key: '_onmseUpdateEnd', + value: function _onmseUpdateEnd() { + if (!this._config.lazyLoad || this._config.isLive) { + return; + } + var buffered = this._mediaElement.buffered; + var currentTime = this._mediaElement.currentTime; + var currentRangeStart = 0; + var currentRangeEnd = 0; + for (var i = 0; i < buffered.length; i++) { + var start = buffered.start(i); + var end = buffered.end(i); + if (start <= currentTime && currentTime < end) { + currentRangeStart = start; + currentRangeEnd = end; + break; + } + } + if (currentRangeEnd >= currentTime + this._config.lazyLoadMaxDuration && this._progressChecker == null) { + _logger2.default.v(this.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task'); + this._suspendTransmuxer(); + } + } + }, { + key: '_onmseBufferFull', + value: function _onmseBufferFull() { + _logger2.default.v(this.TAG, 'MSE SourceBuffer is full, suspend transmuxing task'); + if (this._progressChecker == null) { + this._suspendTransmuxer(); + } + } + }, { + key: '_suspendTransmuxer', + value: function _suspendTransmuxer() { + if (this._transmuxer) { + this._transmuxer.pause(); + if (this._progressChecker == null) { + this._progressChecker = window.setInterval(this._checkProgressAndResume.bind(this), 1000); + } + } + } + }, { + key: '_checkProgressAndResume', + value: function _checkProgressAndResume() { + var currentTime = this._mediaElement.currentTime; + var buffered = this._mediaElement.buffered; + var needResume = false; + for (var i = 0; i < buffered.length; i++) { + var from = buffered.start(i); + var to = buffered.end(i); + if (currentTime >= from && currentTime < to) { + if (currentTime >= to - this._config.lazyLoadRecoverDuration) { + needResume = true; + } + break; + } + } + if (needResume) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + if (needResume) { + _logger2.default.v(this.TAG, 'Continue loading from paused position'); + this._transmuxer.resume(); + } + } + } + }, { + key: '_isTimepointBuffered', + value: function _isTimepointBuffered(seconds) { + var buffered = this._mediaElement.buffered; + for (var i = 0; i < buffered.length; i++) { + var from = buffered.start(i); + var to = buffered.end(i); + if (seconds >= from && seconds < to) { + return true; + } + } + return false; + } + }, { + key: '_internalSeek', + value: function _internalSeek(seconds) { + var directSeek = this._isTimepointBuffered(seconds); + var directSeekBegin = false; + var directSeekBeginTime = 0; + if (seconds < 1.0 && this._mediaElement.buffered.length > 0) { + var videoBeginTime = this._mediaElement.buffered.start(0); + if (videoBeginTime < 1.0 && seconds < videoBeginTime || _browser2.default.safari) { + directSeekBegin = true; + directSeekBeginTime = _browser2.default.safari ? 0.1 : videoBeginTime; + } + } + if (directSeekBegin) { + this._requestSetTime = true; + this._mediaElement.currentTime = directSeekBeginTime; + } else if (directSeek) { + if (!this._alwaysSeekKeyframe) { + this._requestSetTime = true; + this._mediaElement.currentTime = seconds; + } else { + var idr = this._msectl.getNearestKeyframe(Math.floor(seconds * 1000)); + this._requestSetTime = true; + if (idr != null) { + this._mediaElement.currentTime = idr.dts / 1000; + } else { + this._mediaElement.currentTime = seconds; + } + } + if (this._progressChecker != null) { + this._checkProgressAndResume(); + } + } else { + if (this._progressChecker != null) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + } + this._msectl.seek(seconds); + this._transmuxer.seek(Math.floor(seconds * 1000)); + if (this._config.accurateSeek) { + this._requestSetTime = true; + this._mediaElement.currentTime = seconds; + } + } + } + }, { + key: '_checkAndApplyUnbufferedSeekpoint', + value: function _checkAndApplyUnbufferedSeekpoint() { + if (this._seekpointRecord) { + if (this._seekpointRecord.recordTime <= this._now() - 100) { + var target = this._mediaElement.currentTime; + this._seekpointRecord = null; + if (!this._isTimepointBuffered(target)) { + if (this._progressChecker != null) { + window.clearTimeout(this._progressChecker); + this._progressChecker = null; + } + this._msectl.seek(target); + this._transmuxer.seek(Math.floor(target * 1000)); + if (this._config.accurateSeek) { + this._requestSetTime = true; + this._mediaElement.currentTime = target; + } + } + } else { + window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50); + } + } + } + }, { + key: '_checkAndResumeStuckPlayback', + value: function _checkAndResumeStuckPlayback(stalled) { + var media = this._mediaElement; + if (stalled || !this._receivedCanPlay || media.readyState < 2) { + var buffered = media.buffered; + if (buffered.length > 0 && media.currentTime < buffered.start(0)) { + _logger2.default.w(this.TAG, 'Playback seems stuck at ' + media.currentTime + ', seek to ' + buffered.start(0)); + this._requestSetTime = true; + this._mediaElement.currentTime = buffered.start(0); + this._mediaElement.removeEventListener('progress', this.e.onvProgress); + } + } else { + this._mediaElement.removeEventListener('progress', this.e.onvProgress); + } + } + }, { + key: '_onvLoadedMetadata', + value: function _onvLoadedMetadata(e) { + if (this._pendingSeekTime != null) { + this._mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } + } + }, { + key: '_onvSeeking', + value: function _onvSeeking(e) { + var target = this._mediaElement.currentTime; + var buffered = this._mediaElement.buffered; + if (this._requestSetTime) { + this._requestSetTime = false; + return; + } + if (target < 1.0 && buffered.length > 0) { + var videoBeginTime = buffered.start(0); + if (videoBeginTime < 1.0 && target < videoBeginTime || _browser2.default.safari) { + this._requestSetTime = true; + this._mediaElement.currentTime = _browser2.default.safari ? 0.1 : videoBeginTime; + return; + } + } + if (this._isTimepointBuffered(target)) { + if (this._alwaysSeekKeyframe) { + var idr = this._msectl.getNearestKeyframe(Math.floor(target * 1000)); + if (idr != null) { + this._requestSetTime = true; + this._mediaElement.currentTime = idr.dts / 1000; + } + } + if (this._progressChecker != null) { + this._checkProgressAndResume(); + } + return; + } + this._seekpointRecord = { + seekPoint: target, + recordTime: this._now() + }; + window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50); + } + }, { + key: '_onvCanPlay', + value: function _onvCanPlay(e) { + this._receivedCanPlay = true; + this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay); + } + }, { + key: '_onvStalled', + value: function _onvStalled(e) { + this._checkAndResumeStuckPlayback(true); + } + }, { + key: '_onvProgress', + value: function _onvProgress(e) { + this._checkAndResumeStuckPlayback(); + } + }, { + key: 'type', + get: function get() { + return this._type; + } + }, { + key: 'buffered', + get: function get() { + return this._mediaElement.buffered; + } + }, { + key: 'duration', + get: function get() { + return this._mediaElement.duration; + } + }, { + key: 'volume', + get: function get() { + return this._mediaElement.volume; + }, + set: function set(value) { + this._mediaElement.volume = value; + } + }, { + key: 'muted', + get: function get() { + return this._mediaElement.muted; + }, + set: function set(muted) { + this._mediaElement.muted = muted; + } + }, { + key: 'currentTime', + get: function get() { + if (this._mediaElement) { + return this._mediaElement.currentTime; + } + return 0; + }, + set: function set(seconds) { + if (this._mediaElement) { + this._internalSeek(seconds); + } else { + this._pendingSeekTime = seconds; + } + } + }, { + key: 'mediaInfo', + get: function get() { + return Object.assign({}, this._mediaInfo); + } + }, { + key: 'statisticsInfo', + get: function get() { + if (this._statisticsInfo == null) { + this._statisticsInfo = {}; + } + this._statisticsInfo = this._fillStatisticsInfo(this._statisticsInfo); + return Object.assign({}, this._statisticsInfo); + } + }]); + return FlvPlayer; + }(); + exports.default = FlvPlayer; + }, { + "../config.js": 5, + "../core/mse-controller.js": 9, + "../core/mse-events.js": 10, + "../core/transmuxer.js": 11, + "../core/transmuxing-events.js": 13, + "../utils/browser.js": 39, + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./player-errors.js": 34, + "./player-events.js": 35, + "events": 2 + }], + 33: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _playerEvents = _dereq_('./player-events.js'); + var _playerEvents2 = _interopRequireDefault(_playerEvents); + var _config = _dereq_('../config.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var NativePlayer = function() { + function NativePlayer(mediaDataSource, config) { + _classCallCheck(this, NativePlayer); + this.TAG = 'NativePlayer'; + this._type = 'NativePlayer'; + this._emitter = new _events2.default(); + this._config = (0, _config.createDefaultConfig)(); + if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') { + Object.assign(this._config, config); + } + if (mediaDataSource.type.toLowerCase() === 'flv') { + throw new _exception.InvalidArgumentException('NativePlayer does\'t support flv MediaDataSource input!'); + } + if (mediaDataSource.hasOwnProperty('segments')) { + throw new _exception.InvalidArgumentException('NativePlayer(' + mediaDataSource.type + ') doesn\'t support multipart playback!'); + } + this.e = { + onvLoadedMetadata: this._onvLoadedMetadata.bind(this) + }; + this._pendingSeekTime = null; + this._statisticsReporter = null; + this._mediaDataSource = mediaDataSource; + this._mediaElement = null; + } + _createClass(NativePlayer, [{ + key: 'destroy', + value: function destroy() { + if (this._mediaElement) { + this.unload(); + this.detachMediaElement(); + } + this.e = null; + this._mediaDataSource = null; + this._emitter.removeAllListeners(); + this._emitter = null; + } + }, { + key: 'on', + value: function on(event, listener) { + var _this = this; + if (event === _playerEvents2.default.MEDIA_INFO) { + if (this._mediaElement != null && this._mediaElement.readyState !== 0) { + Promise.resolve().then(function() { + _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo); + }); + } + } else if (event === _playerEvents2.default.STATISTICS_INFO) { + if (this._mediaElement != null && this._mediaElement.readyState !== 0) { + Promise.resolve().then(function() { + _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo); + }); + } + } + this._emitter.addListener(event, listener); + } + }, { + key: 'off', + value: function off(event, listener) { + this._emitter.removeListener(event, listener); + } + }, { + key: 'attachMediaElement', + value: function attachMediaElement(mediaElement) { + this._mediaElement = mediaElement; + mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata); + if (this._pendingSeekTime != null) { + try { + mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } catch (e) {} + } + } + }, { + key: 'detachMediaElement', + value: function detachMediaElement() { + if (this._mediaElement) { + this._mediaElement.src = ''; + this._mediaElement.removeAttribute('src'); + this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata); + this._mediaElement = null; + } + if (this._statisticsReporter != null) { + window.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + } + }, { + key: 'load', + value: function load() { + if (!this._mediaElement) { + throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!'); + } + this._mediaElement.src = this._mediaDataSource.url; + if (this._mediaElement.readyState > 0) { + this._mediaElement.currentTime = 0; + } + this._mediaElement.preload = 'auto'; + this._mediaElement.load(); + this._statisticsReporter = window.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval); + } + }, { + key: 'unload', + value: function unload() { + if (this._mediaElement) { + this._mediaElement.src = ''; + this._mediaElement.removeAttribute('src'); + } + if (this._statisticsReporter != null) { + window.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + } + }, { + key: 'play', + value: function play() { + return this._mediaElement.play(); + } + }, { + key: 'pause', + value: function pause() { + this._mediaElement.pause(); + } + }, { + key: '_onvLoadedMetadata', + value: function _onvLoadedMetadata(e) { + if (this._pendingSeekTime != null) { + this._mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } + this._emitter.emit(_playerEvents2.default.MEDIA_INFO, this.mediaInfo); + } + }, { + key: '_reportStatisticsInfo', + value: function _reportStatisticsInfo() { + this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, this.statisticsInfo); + } + }, { + key: 'type', + get: function get() { + return this._type; + } + }, { + key: 'buffered', + get: function get() { + return this._mediaElement.buffered; + } + }, { + key: 'duration', + get: function get() { + return this._mediaElement.duration; + } + }, { + key: 'volume', + get: function get() { + return this._mediaElement.volume; + }, + set: function set(value) { + this._mediaElement.volume = value; + } + }, { + key: 'muted', + get: function get() { + return this._mediaElement.muted; + }, + set: function set(muted) { + this._mediaElement.muted = muted; + } + }, { + key: 'currentTime', + get: function get() { + if (this._mediaElement) { + return this._mediaElement.currentTime; + } + return 0; + }, + set: function set(seconds) { + if (this._mediaElement) { + this._mediaElement.currentTime = seconds; + } else { + this._pendingSeekTime = seconds; + } + } + }, { + key: 'mediaInfo', + get: function get() { + var mediaPrefix = this._mediaElement instanceof HTMLAudioElement ? 'audio/' : 'video/'; + var info = { + mimeType: mediaPrefix + this._mediaDataSource.type + }; + if (this._mediaElement) { + info.duration = Math.floor(this._mediaElement.duration * 1000); + if (this._mediaElement instanceof HTMLVideoElement) { + info.width = this._mediaElement.videoWidth; + info.height = this._mediaElement.videoHeight; + } + } + return info; + } + }, { + key: 'statisticsInfo', + get: function get() { + var info = { + playerType: this._type, + url: this._mediaDataSource.url + }; + if (!(this._mediaElement instanceof HTMLVideoElement)) { + return info; + } + var hasQualityInfo = true; + var decoded = 0; + var dropped = 0; + if (this._mediaElement.getVideoPlaybackQuality) { + var quality = this._mediaElement.getVideoPlaybackQuality(); + decoded = quality.totalVideoFrames; + dropped = quality.droppedVideoFrames; + } else if (this._mediaElement.webkitDecodedFrameCount != undefined) { + decoded = this._mediaElement.webkitDecodedFrameCount; + dropped = this._mediaElement.webkitDroppedFrameCount; + } else { + hasQualityInfo = false; + } + if (hasQualityInfo) { + info.decodedFrames = decoded; + info.droppedFrames = dropped; + } + return info; + } + }]); + return NativePlayer; + }(); + exports.default = NativePlayer; + }, { + "../config.js": 5, + "../utils/exception.js": 40, + "./player-events.js": 35, + "events": 2 + }], + 34: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.ErrorDetails = exports.ErrorTypes = undefined; + var _loader = _dereq_('../io/loader.js'); + var _demuxErrors = _dereq_('../demux/demux-errors.js'); + var _demuxErrors2 = _interopRequireDefault(_demuxErrors); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + var ErrorTypes = exports.ErrorTypes = { + NETWORK_ERROR: 'NetworkError', + MEDIA_ERROR: 'MediaError', + OTHER_ERROR: 'OtherError' + }; + var ErrorDetails = exports.ErrorDetails = { + NETWORK_EXCEPTION: _loader.LoaderErrors.EXCEPTION, + NETWORK_STATUS_CODE_INVALID: _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, + NETWORK_TIMEOUT: _loader.LoaderErrors.CONNECTING_TIMEOUT, + NETWORK_UNRECOVERABLE_EARLY_EOF: _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF, + MEDIA_MSE_ERROR: 'MediaMSEError', + MEDIA_FORMAT_ERROR: _demuxErrors2.default.FORMAT_ERROR, + MEDIA_FORMAT_UNSUPPORTED: _demuxErrors2.default.FORMAT_UNSUPPORTED, + MEDIA_CODEC_UNSUPPORTED: _demuxErrors2.default.CODEC_UNSUPPORTED + }; + }, { + "../demux/demux-errors.js": 16, + "../io/loader.js": 24 + }], + 35: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var PlayerEvents = { + ERROR: 'error', + LOADING_COMPLETE: 'loading_complete', + RECOVERED_EARLY_EOF: 'recovered_early_eof', + MEDIA_INFO: 'media_info', + METADATA_ARRIVED: 'metadata_arrived', + SCRIPTDATA_ARRIVED: 'scriptdata_arrived', + STATISTICS_INFO: 'statistics_info' + }; + exports.default = PlayerEvents; + }, {}], + 36: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var AAC = function() { + function AAC() { + _classCallCheck(this, AAC); + } + _createClass(AAC, null, [{ + key: 'getSilentFrame', + value: function getSilentFrame(codec, channelCount) { + if (codec === 'mp4a.40.2') { + if (channelCount === 1) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]); + } else if (channelCount === 2) { + return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]); + } else if (channelCount === 3) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]); + } else if (channelCount === 4) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]); + } else if (channelCount === 5) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]); + } else if (channelCount === 6) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]); + } + } else { + if (channelCount === 1) { + return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); + } else if (channelCount === 2) { + return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); + } else if (channelCount === 3) { + return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); + } + } + return null; + } + }]); + return AAC; + }(); + exports.default = AAC; + }, {}], + 37: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var MP4 = function() { + function MP4() { + _classCallCheck(this, MP4); + } + _createClass(MP4, null, [{ + key: 'init', + value: function init() { + MP4.types = { + avc1: [], + avcC: [], + btrt: [], + dinf: [], + dref: [], + esds: [], + ftyp: [], + hdlr: [], + mdat: [], + mdhd: [], + mdia: [], + mfhd: [], + minf: [], + moof: [], + moov: [], + mp4a: [], + mvex: [], + mvhd: [], + sdtp: [], + stbl: [], + stco: [], + stsc: [], + stsd: [], + stsz: [], + stts: [], + tfdt: [], + tfhd: [], + traf: [], + trak: [], + trun: [], + trex: [], + tkhd: [], + vmhd: [], + smhd: [], + '.mp3': [] + }; + for (var name in MP4.types) { + if (MP4.types.hasOwnProperty(name)) { + MP4.types[name] = [name.charCodeAt(0), name.charCodeAt(1), name.charCodeAt(2), name.charCodeAt(3)]; + } + } + var constants = MP4.constants = {}; + constants.FTYP = new Uint8Array([0x69, 0x73, 0x6F, 0x6D, 0x0, 0x0, 0x0, 0x1, 0x69, 0x73, 0x6F, 0x6D, 0x61, 0x76, 0x63, 0x31]); + constants.STSD_PREFIX = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]); + constants.STTS = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + constants.STSC = constants.STCO = constants.STTS; + constants.STSZ = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + constants.HDLR_VIDEO = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00]); + constants.HDLR_AUDIO = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6F, 0x75, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00]); + constants.DREF = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x01]); + constants.SMHD = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + constants.VMHD = new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + } + }, { + key: 'box', + value: function box(type) { + var size = 8; + var result = null; + var datas = Array.prototype.slice.call(arguments, 1); + var arrayCount = datas.length; + for (var i = 0; i < arrayCount; i++) { + size += datas[i].byteLength; + } + result = new Uint8Array(size); + result[0] = size >>> 24 & 0xFF; + result[1] = size >>> 16 & 0xFF; + result[2] = size >>> 8 & 0xFF; + result[3] = size & 0xFF; + result.set(type, 4); + var offset = 8; + for (var _i = 0; _i < arrayCount; _i++) { + result.set(datas[_i], offset); + offset += datas[_i].byteLength; + } + return result; + } + }, { + key: 'generateInitSegment', + value: function generateInitSegment(meta) { + var ftyp = MP4.box(MP4.types.ftyp, MP4.constants.FTYP); + var moov = MP4.moov(meta); + var result = new Uint8Array(ftyp.byteLength + moov.byteLength); + result.set(ftyp, 0); + result.set(moov, ftyp.byteLength); + return result; + } + }, { + key: 'moov', + value: function moov(meta) { + var mvhd = MP4.mvhd(meta.timescale, meta.duration); + var trak = MP4.trak(meta); + var mvex = MP4.mvex(meta); + return MP4.box(MP4.types.moov, mvhd, trak, mvex); + } + }, { + key: 'mvhd', + value: function mvhd(timescale, duration) { + return MP4.box(MP4.types.mvhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, timescale >>> 24 & 0xFF, timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF])); + } + }, { + key: 'trak', + value: function trak(meta) { + return MP4.box(MP4.types.trak, MP4.tkhd(meta), MP4.mdia(meta)); + } + }, { + key: 'tkhd', + value: function tkhd(meta) { + var trackId = meta.id, + duration = meta.duration; + var width = meta.presentWidth, + height = meta.presentHeight; + return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, trackId >>> 24 & 0xFF, trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x00, duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, width >>> 8 & 0xFF, width & 0xFF, 0x00, 0x00, height >>> 8 & 0xFF, height & 0xFF, 0x00, 0x00])); + } + }, { + key: 'mdia', + value: function mdia(meta) { + return MP4.box(MP4.types.mdia, MP4.mdhd(meta), MP4.hdlr(meta), MP4.minf(meta)); + } + }, { + key: 'mdhd', + value: function mdhd(meta) { + var timescale = meta.timescale; + var duration = meta.duration; + return MP4.box(MP4.types.mdhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, timescale >>> 24 & 0xFF, timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x55, 0xC4, 0x00, 0x00])); + } + }, { + key: 'hdlr', + value: function hdlr(meta) { + var data = null; + if (meta.type === 'audio') { + data = MP4.constants.HDLR_AUDIO; + } else { + data = MP4.constants.HDLR_VIDEO; + } + return MP4.box(MP4.types.hdlr, data); + } + }, { + key: 'minf', + value: function minf(meta) { + var xmhd = null; + if (meta.type === 'audio') { + xmhd = MP4.box(MP4.types.smhd, MP4.constants.SMHD); + } else { + xmhd = MP4.box(MP4.types.vmhd, MP4.constants.VMHD); + } + return MP4.box(MP4.types.minf, xmhd, MP4.dinf(), MP4.stbl(meta)); + } + }, { + key: 'dinf', + value: function dinf() { + var result = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, MP4.constants.DREF)); + return result; + } + }, { + key: 'stbl', + value: function stbl(meta) { + var result = MP4.box(MP4.types.stbl, MP4.stsd(meta), MP4.box(MP4.types.stts, MP4.constants.STTS), MP4.box(MP4.types.stsc, MP4.constants.STSC), MP4.box(MP4.types.stsz, MP4.constants.STSZ), MP4.box(MP4.types.stco, MP4.constants.STCO)); + return result; + } + }, { + key: 'stsd', + value: function stsd(meta) { + if (meta.type === 'audio') { + if (meta.codec === 'mp3') { + return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp3(meta)); + } + return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp4a(meta)); + } else { + return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.avc1(meta)); + } + } + }, { + key: 'mp3', + value: function mp3(meta) { + var channelCount = meta.channelCount; + var sampleRate = meta.audioSampleRate; + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, sampleRate >>> 8 & 0xFF, sampleRate & 0xFF, 0x00, 0x00]); + return MP4.box(MP4.types['.mp3'], data); + } + }, { + key: 'mp4a', + value: function mp4a(meta) { + var channelCount = meta.channelCount; + var sampleRate = meta.audioSampleRate; + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, sampleRate >>> 8 & 0xFF, sampleRate & 0xFF, 0x00, 0x00]); + return MP4.box(MP4.types.mp4a, data, MP4.esds(meta)); + } + }, { + key: 'esds', + value: function esds(meta) { + var config = meta.config || []; + var configSize = config.length; + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x03, 0x17 + configSize, 0x00, 0x01, 0x00, 0x04, 0x0F + configSize, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05].concat([configSize]).concat(config).concat([0x06, 0x01, 0x02])); + return MP4.box(MP4.types.esds, data); + } + }, { + key: 'avc1', + value: function avc1(meta) { + var avcc = meta.avcc; + var width = meta.codecWidth, + height = meta.codecHeight; + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, width >>> 8 & 0xFF, width & 0xFF, height >>> 8 & 0xFF, height & 0xFF, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x78, 0x71, 0x71, 0x2F, 0x66, 0x6C, 0x76, 0x2E, 0x6A, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF]); + return MP4.box(MP4.types.avc1, data, MP4.box(MP4.types.avcC, avcc)); + } + }, { + key: 'mvex', + value: function mvex(meta) { + return MP4.box(MP4.types.mvex, MP4.trex(meta)); + } + }, { + key: 'trex', + value: function trex(meta) { + var trackId = meta.id; + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, trackId >>> 24 & 0xFF, trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01]); + return MP4.box(MP4.types.trex, data); + } + }, { + key: 'moof', + value: function moof(track, baseMediaDecodeTime) { + return MP4.box(MP4.types.moof, MP4.mfhd(track.sequenceNumber), MP4.traf(track, baseMediaDecodeTime)); + } + }, { + key: 'mfhd', + value: function mfhd(sequenceNumber) { + var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, sequenceNumber >>> 24 & 0xFF, sequenceNumber >>> 16 & 0xFF, sequenceNumber >>> 8 & 0xFF, sequenceNumber & 0xFF]); + return MP4.box(MP4.types.mfhd, data); + } + }, { + key: 'traf', + value: function traf(track, baseMediaDecodeTime) { + var trackId = track.id; + var tfhd = MP4.box(MP4.types.tfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, trackId >>> 24 & 0xFF, trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF])); + var tfdt = MP4.box(MP4.types.tfdt, new Uint8Array([0x00, 0x00, 0x00, 0x00, baseMediaDecodeTime >>> 24 & 0xFF, baseMediaDecodeTime >>> 16 & 0xFF, baseMediaDecodeTime >>> 8 & 0xFF, baseMediaDecodeTime & 0xFF])); + var sdtp = MP4.sdtp(track); + var trun = MP4.trun(track, sdtp.byteLength + 16 + 16 + 8 + 16 + 8 + 8); + return MP4.box(MP4.types.traf, tfhd, tfdt, trun, sdtp); + } + }, { + key: 'sdtp', + value: function sdtp(track) { + var samples = track.samples || []; + var sampleCount = samples.length; + var data = new Uint8Array(4 + sampleCount); + for (var i = 0; i < sampleCount; i++) { + var flags = samples[i].flags; + data[i + 4] = flags.isLeading << 6 | flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy; + } + return MP4.box(MP4.types.sdtp, data); + } + }, { + key: 'trun', + value: function trun(track, offset) { + var samples = track.samples || []; + var sampleCount = samples.length; + var dataSize = 12 + 16 * sampleCount; + var data = new Uint8Array(dataSize); + offset += 8 + dataSize; + data.set([0x00, 0x00, 0x0F, 0x01, sampleCount >>> 24 & 0xFF, sampleCount >>> 16 & 0xFF, sampleCount >>> 8 & 0xFF, sampleCount & 0xFF, offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF], 0); + for (var i = 0; i < sampleCount; i++) { + var duration = samples[i].duration; + var size = samples[i].size; + var flags = samples[i].flags; + var cts = samples[i].cts; + data.set([duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, size >>> 24 & 0xFF, size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, flags.isLeading << 2 | flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.isNonSync, 0x00, 0x00, cts >>> 24 & 0xFF, cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF], 12 + 16 * i); + } + return MP4.box(MP4.types.trun, data); + } + }, { + key: 'mdat', + value: function mdat(data) { + return MP4.box(MP4.types.mdat, data); + } + }]); + return MP4; + }(); + MP4.init(); + exports.default = MP4; + }, {}], + 38: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _logger = _dereq_('../utils/logger.js'); + var _logger2 = _interopRequireDefault(_logger); + var _mp4Generator = _dereq_('./mp4-generator.js'); + var _mp4Generator2 = _interopRequireDefault(_mp4Generator); + var _aacSilent = _dereq_('./aac-silent.js'); + var _aacSilent2 = _interopRequireDefault(_aacSilent); + var _browser = _dereq_('../utils/browser.js'); + var _browser2 = _interopRequireDefault(_browser); + var _mediaSegmentInfo = _dereq_('../core/media-segment-info.js'); + var _exception = _dereq_('../utils/exception.js'); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var MP4Remuxer = function() { + function MP4Remuxer(config) { + _classCallCheck(this, MP4Remuxer); + this.TAG = 'MP4Remuxer'; + this._config = config; + this._isLive = config.isLive === true ? true : false; + this._dtsBase = -1; + this._dtsBaseInited = false; + this._audioDtsBase = Infinity; + this._videoDtsBase = Infinity; + this._audioNextDts = undefined; + this._videoNextDts = undefined; + this._audioStashedLastSample = null; + this._videoStashedLastSample = null; + this._audioMeta = null; + this._videoMeta = null; + this._audioSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('audio'); + this._videoSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('video'); + this._onInitSegment = null; + this._onMediaSegment = null; + this._forceFirstIDR = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661) ? true : false; + this._fillSilentAfterSeek = _browser2.default.msedge || _browser2.default.msie; + this._mp3UseMpegAudio = !_browser2.default.firefox; + this._fillAudioTimestampGap = this._config.fixAudioTimestampGap; + } + _createClass(MP4Remuxer, [{ + key: 'destroy', + value: function destroy() { + this._dtsBase = -1; + this._dtsBaseInited = false; + this._audioMeta = null; + this._videoMeta = null; + this._audioSegmentInfoList.clear(); + this._audioSegmentInfoList = null; + this._videoSegmentInfoList.clear(); + this._videoSegmentInfoList = null; + this._onInitSegment = null; + this._onMediaSegment = null; + } + }, { + key: 'bindDataSource', + value: function bindDataSource(producer) { + producer.onDataAvailable = this.remux.bind(this); + producer.onTrackMetadata = this._onTrackMetadataReceived.bind(this); + return this; + } + }, { + key: 'insertDiscontinuity', + value: function insertDiscontinuity() { + this._audioNextDts = this._videoNextDts = undefined; + } + }, { + key: 'seek', + value: function seek(originalDts) { + this._audioStashedLastSample = null; + this._videoStashedLastSample = null; + this._videoSegmentInfoList.clear(); + this._audioSegmentInfoList.clear(); + } + }, { + key: 'remux', + value: function remux(audioTrack, videoTrack) { + if (!this._onMediaSegment) { + throw new _exception.IllegalStateException('MP4Remuxer: onMediaSegment callback must be specificed!'); + } + if (!this._dtsBaseInited) { + this._calculateDtsBase(audioTrack, videoTrack); + } + this._remuxVideo(videoTrack); + this._remuxAudio(audioTrack); + } + }, { + key: '_onTrackMetadataReceived', + value: function _onTrackMetadataReceived(type, metadata) { + var metabox = null; + var container = 'mp4'; + var codec = metadata.codec; + if (type === 'audio') { + this._audioMeta = metadata; + if (metadata.codec === 'mp3' && this._mp3UseMpegAudio) { + container = 'mpeg'; + codec = ''; + metabox = new Uint8Array(); + } else { + metabox = _mp4Generator2.default.generateInitSegment(metadata); + } + } else if (type === 'video') { + this._videoMeta = metadata; + metabox = _mp4Generator2.default.generateInitSegment(metadata); + } else { + return; + } + if (!this._onInitSegment) { + throw new _exception.IllegalStateException('MP4Remuxer: onInitSegment callback must be specified!'); + } + this._onInitSegment(type, { + type: type, + data: metabox.buffer, + codec: codec, + container: type + '/' + container, + mediaDuration: metadata.duration + }); + } + }, { + key: '_calculateDtsBase', + value: function _calculateDtsBase(audioTrack, videoTrack) { + if (this._dtsBaseInited) { + return; + } + if (audioTrack.samples && audioTrack.samples.length) { + this._audioDtsBase = audioTrack.samples[0].dts; + } + if (videoTrack.samples && videoTrack.samples.length) { + this._videoDtsBase = videoTrack.samples[0].dts; + } + this._dtsBase = Math.min(this._audioDtsBase, this._videoDtsBase); + this._dtsBaseInited = true; + } + }, { + key: 'flushStashedSamples', + value: function flushStashedSamples() { + var videoSample = this._videoStashedLastSample; + var audioSample = this._audioStashedLastSample; + var videoTrack = { + type: 'video', + id: 1, + sequenceNumber: 0, + samples: [], + length: 0 + }; + if (videoSample != null) { + videoTrack.samples.push(videoSample); + videoTrack.length = videoSample.length; + } + var audioTrack = { + type: 'audio', + id: 2, + sequenceNumber: 0, + samples: [], + length: 0 + }; + if (audioSample != null) { + audioTrack.samples.push(audioSample); + audioTrack.length = audioSample.length; + } + this._videoStashedLastSample = null; + this._audioStashedLastSample = null; + this._remuxVideo(videoTrack, true); + this._remuxAudio(audioTrack, true); + } + }, { + key: '_remuxAudio', + value: function _remuxAudio(audioTrack, force) { + if (this._audioMeta == null) { + return; + } + var track = audioTrack; + var samples = track.samples; + var dtsCorrection = undefined; + var firstDts = -1, + lastDts = -1, + lastPts = -1; + var refSampleDuration = this._audioMeta.refSampleDuration; + var mpegRawTrack = this._audioMeta.codec === 'mp3' && this._mp3UseMpegAudio; + var firstSegmentAfterSeek = this._dtsBaseInited && this._audioNextDts === undefined; + var insertPrefixSilentFrame = false; + if (!samples || samples.length === 0) { + return; + } + if (samples.length === 1 && !force) { + return; + } + var offset = 0; + var mdatbox = null; + var mdatBytes = 0; + if (mpegRawTrack) { + offset = 0; + mdatBytes = track.length; + } else { + offset = 8; + mdatBytes = 8 + track.length; + } + var lastSample = null; + if (samples.length > 1) { + lastSample = samples.pop(); + mdatBytes -= lastSample.length; + } + if (this._audioStashedLastSample != null) { + var sample = this._audioStashedLastSample; + this._audioStashedLastSample = null; + samples.unshift(sample); + mdatBytes += sample.length; + } + if (lastSample != null) { + this._audioStashedLastSample = lastSample; + } + var firstSampleOriginalDts = samples[0].dts - this._dtsBase; + if (this._audioNextDts) { + dtsCorrection = firstSampleOriginalDts - this._audioNextDts; + } else { + if (this._audioSegmentInfoList.isEmpty()) { + dtsCorrection = 0; + if (this._fillSilentAfterSeek && !this._videoSegmentInfoList.isEmpty()) { + if (this._audioMeta.originalCodec !== 'mp3') { + insertPrefixSilentFrame = true; + } + } + } else { + var _lastSample = this._audioSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts); + if (_lastSample != null) { + var distance = firstSampleOriginalDts - (_lastSample.originalDts + _lastSample.duration); + if (distance <= 3) { + distance = 0; + } + var expectedDts = _lastSample.dts + _lastSample.duration + distance; + dtsCorrection = firstSampleOriginalDts - expectedDts; + } else { + dtsCorrection = 0; + } + } + } + if (insertPrefixSilentFrame) { + var firstSampleDts = firstSampleOriginalDts - dtsCorrection; + var videoSegment = this._videoSegmentInfoList.getLastSegmentBefore(firstSampleOriginalDts); + if (videoSegment != null && videoSegment.beginDts < firstSampleDts) { + var silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount); + if (silentUnit) { + var dts = videoSegment.beginDts; + var silentFrameDuration = firstSampleDts - videoSegment.beginDts; + _logger2.default.v(this.TAG, 'InsertPrefixSilentAudio: dts: ' + dts + ', duration: ' + silentFrameDuration); + samples.unshift({ + unit: silentUnit, + dts: dts, + pts: dts + }); + mdatBytes += silentUnit.byteLength; + } + } else { + insertPrefixSilentFrame = false; + } + } + var mp4Samples = []; + for (var i = 0; i < samples.length; i++) { + var _sample = samples[i]; + var unit = _sample.unit; + var originalDts = _sample.dts - this._dtsBase; + var _dts = originalDts - dtsCorrection; + if (firstDts === -1) { + firstDts = _dts; + } + var sampleDuration = 0; + if (i !== samples.length - 1) { + var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - _dts; + } else { + if (lastSample != null) { + var _nextDts = lastSample.dts - this._dtsBase - dtsCorrection; + sampleDuration = _nextDts - _dts; + } else if (mp4Samples.length >= 1) { + sampleDuration = mp4Samples[mp4Samples.length - 1].duration; + } else { + sampleDuration = Math.floor(refSampleDuration); + } + } + var needFillSilentFrames = false; + var silentFrames = null; + if (sampleDuration > refSampleDuration * 1.5 && this._audioMeta.codec !== 'mp3' && this._fillAudioTimestampGap && !_browser2.default.safari) { + needFillSilentFrames = true; + var delta = Math.abs(sampleDuration - refSampleDuration); + var frameCount = Math.ceil(delta / refSampleDuration); + var currentDts = _dts + refSampleDuration; + _logger2.default.w(this.TAG, 'Large audio timestamp gap detected, may cause AV sync to drift. ' + 'Silent frames will be generated to avoid unsync.\n' + ('dts: ' + (_dts + sampleDuration) + ' ms, expected: ' + (_dts + Math.round(refSampleDuration)) + ' ms, ') + ('delta: ' + Math.round(delta) + ' ms, generate: ' + frameCount + ' frames')); + var _silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount); + if (_silentUnit == null) { + _logger2.default.w(this.TAG, 'Unable to generate silent frame for ' + (this._audioMeta.originalCodec + ' with ' + this._audioMeta.channelCount + ' channels, repeat last frame')); + _silentUnit = unit; + } + silentFrames = []; + for (var j = 0; j < frameCount; j++) { + var intDts = Math.round(currentDts); + if (silentFrames.length > 0) { + var previousFrame = silentFrames[silentFrames.length - 1]; + previousFrame.duration = intDts - previousFrame.dts; + } + var frame = { + dts: intDts, + pts: intDts, + cts: 0, + unit: _silentUnit, + size: _silentUnit.byteLength, + duration: 0, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: 1, + isDependedOn: 0, + hasRedundancy: 0 + } + }; + silentFrames.push(frame); + mdatBytes += frame.size; + currentDts += refSampleDuration; + } + var lastFrame = silentFrames[silentFrames.length - 1]; + lastFrame.duration = _dts + sampleDuration - lastFrame.dts; + sampleDuration = Math.round(refSampleDuration); + } + mp4Samples.push({ + dts: _dts, + pts: _dts, + cts: 0, + unit: _sample.unit, + size: _sample.unit.byteLength, + duration: sampleDuration, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: 1, + isDependedOn: 0, + hasRedundancy: 0 + } + }); + if (needFillSilentFrames) { + mp4Samples.push.apply(mp4Samples, silentFrames); + } + } + if (mpegRawTrack) { + mdatbox = new Uint8Array(mdatBytes); + } else { + mdatbox = new Uint8Array(mdatBytes); + mdatbox[0] = mdatBytes >>> 24 & 0xFF; + mdatbox[1] = mdatBytes >>> 16 & 0xFF; + mdatbox[2] = mdatBytes >>> 8 & 0xFF; + mdatbox[3] = mdatBytes & 0xFF; + mdatbox.set(_mp4Generator2.default.types.mdat, 4); + } + for (var _i = 0; _i < mp4Samples.length; _i++) { + var _unit = mp4Samples[_i].unit; + mdatbox.set(_unit, offset); + offset += _unit.byteLength; + } + var latest = mp4Samples[mp4Samples.length - 1]; + lastDts = latest.dts + latest.duration; + this._audioNextDts = lastDts; + var info = new _mediaSegmentInfo.MediaSegmentInfo(); + info.beginDts = firstDts; + info.endDts = lastDts; + info.beginPts = firstDts; + info.endPts = lastDts; + info.originalBeginDts = mp4Samples[0].originalDts; + info.originalEndDts = latest.originalDts + latest.duration; + info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, false); + info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, false); + if (!this._isLive) { + this._audioSegmentInfoList.append(info); + } + track.samples = mp4Samples; + track.sequenceNumber++; + var moofbox = null; + if (mpegRawTrack) { + moofbox = new Uint8Array(); + } else { + moofbox = _mp4Generator2.default.moof(track, firstDts); + } + track.samples = []; + track.length = 0; + var segment = { + type: 'audio', + data: this._mergeBoxes(moofbox, mdatbox).buffer, + sampleCount: mp4Samples.length, + info: info + }; + if (mpegRawTrack && firstSegmentAfterSeek) { + segment.timestampOffset = firstDts; + } + this._onMediaSegment('audio', segment); + } + }, { + key: '_remuxVideo', + value: function _remuxVideo(videoTrack, force) { + if (this._videoMeta == null) { + return; + } + var track = videoTrack; + var samples = track.samples; + var dtsCorrection = undefined; + var firstDts = -1, + lastDts = -1; + var firstPts = -1, + lastPts = -1; + if (!samples || samples.length === 0) { + return; + } + if (samples.length === 1 && !force) { + return; + } + var offset = 8; + var mdatbox = null; + var mdatBytes = 8 + videoTrack.length; + var lastSample = null; + if (samples.length > 1) { + lastSample = samples.pop(); + mdatBytes -= lastSample.length; + } + if (this._videoStashedLastSample != null) { + var sample = this._videoStashedLastSample; + this._videoStashedLastSample = null; + samples.unshift(sample); + mdatBytes += sample.length; + } + if (lastSample != null) { + this._videoStashedLastSample = lastSample; + } + var firstSampleOriginalDts = samples[0].dts - this._dtsBase; + if (this._videoNextDts) { + dtsCorrection = firstSampleOriginalDts - this._videoNextDts; + } else { + if (this._videoSegmentInfoList.isEmpty()) { + dtsCorrection = 0; + } else { + var _lastSample2 = this._videoSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts); + if (_lastSample2 != null) { + var distance = firstSampleOriginalDts - (_lastSample2.originalDts + _lastSample2.duration); + if (distance <= 3) { + distance = 0; + } + var expectedDts = _lastSample2.dts + _lastSample2.duration + distance; + dtsCorrection = firstSampleOriginalDts - expectedDts; + } else { + dtsCorrection = 0; + } + } + } + var info = new _mediaSegmentInfo.MediaSegmentInfo(); + var mp4Samples = []; + for (var i = 0; i < samples.length; i++) { + var _sample2 = samples[i]; + var originalDts = _sample2.dts - this._dtsBase; + var isKeyframe = _sample2.isKeyframe; + var dts = originalDts - dtsCorrection; + var cts = _sample2.cts; + var pts = dts + cts; + if (firstDts === -1) { + firstDts = dts; + firstPts = pts; + } + var sampleDuration = 0; + if (i !== samples.length - 1) { + var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - dts; + } else { + if (lastSample != null) { + var _nextDts2 = lastSample.dts - this._dtsBase - dtsCorrection; + sampleDuration = _nextDts2 - dts; + } else if (mp4Samples.length >= 1) { + sampleDuration = mp4Samples[mp4Samples.length - 1].duration; + } else { + sampleDuration = Math.floor(this._videoMeta.refSampleDuration); + } + } + if (isKeyframe) { + var syncPoint = new _mediaSegmentInfo.SampleInfo(dts, pts, sampleDuration, _sample2.dts, true); + syncPoint.fileposition = _sample2.fileposition; + info.appendSyncPoint(syncPoint); + } + mp4Samples.push({ + dts: dts, + pts: pts, + cts: cts, + units: _sample2.units, + size: _sample2.length, + isKeyframe: isKeyframe, + duration: sampleDuration, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: isKeyframe ? 2 : 1, + isDependedOn: isKeyframe ? 1 : 0, + hasRedundancy: 0, + isNonSync: isKeyframe ? 0 : 1 + } + }); + } + mdatbox = new Uint8Array(mdatBytes); + mdatbox[0] = mdatBytes >>> 24 & 0xFF; + mdatbox[1] = mdatBytes >>> 16 & 0xFF; + mdatbox[2] = mdatBytes >>> 8 & 0xFF; + mdatbox[3] = mdatBytes & 0xFF; + mdatbox.set(_mp4Generator2.default.types.mdat, 4); + for (var _i2 = 0; _i2 < mp4Samples.length; _i2++) { + var units = mp4Samples[_i2].units; + while (units.length) { + var unit = units.shift(); + var data = unit.data; + mdatbox.set(data, offset); + offset += data.byteLength; + } + } + var latest = mp4Samples[mp4Samples.length - 1]; + lastDts = latest.dts + latest.duration; + lastPts = latest.pts + latest.duration; + this._videoNextDts = lastDts; + info.beginDts = firstDts; + info.endDts = lastDts; + info.beginPts = firstPts; + info.endPts = lastPts; + info.originalBeginDts = mp4Samples[0].originalDts; + info.originalEndDts = latest.originalDts + latest.duration; + info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, mp4Samples[0].isKeyframe); + info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, latest.isKeyframe); + if (!this._isLive) { + this._videoSegmentInfoList.append(info); + } + track.samples = mp4Samples; + track.sequenceNumber++; + if (this._forceFirstIDR) { + var flags = mp4Samples[0].flags; + flags.dependsOn = 2; + flags.isNonSync = 0; + } + var moofbox = _mp4Generator2.default.moof(track, firstDts); + track.samples = []; + track.length = 0; + this._onMediaSegment('video', { + type: 'video', + data: this._mergeBoxes(moofbox, mdatbox).buffer, + sampleCount: mp4Samples.length, + info: info + }); + } + }, { + key: '_mergeBoxes', + value: function _mergeBoxes(moof, mdat) { + var result = new Uint8Array(moof.byteLength + mdat.byteLength); + result.set(moof, 0); + result.set(mdat, moof.byteLength); + return result; + } + }, { + key: 'onInitSegment', + get: function get() { + return this._onInitSegment; + }, + set: function set(callback) { + this._onInitSegment = callback; + } + }, { + key: 'onMediaSegment', + get: function get() { + return this._onMediaSegment; + }, + set: function set(callback) { + this._onMediaSegment = callback; + } + }]); + return MP4Remuxer; + }(); + exports.default = MP4Remuxer; + }, { + "../core/media-segment-info.js": 8, + "../utils/browser.js": 39, + "../utils/exception.js": 40, + "../utils/logger.js": 41, + "./aac-silent.js": 36, + "./mp4-generator.js": 37 + }], + 39: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var Browser = {}; + + function detect() { + var ua = self.navigator.userAgent.toLowerCase(); + var match = /(edge)\/([\w.]+)/.exec(ua) || /(opr)[\/]([\w.]+)/.exec(ua) || /(chrome)[ \/]([\w.]+)/.exec(ua) || /(iemobile)[\/]([\w.]+)/.exec(ua) || /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('trident') >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(firefox)[ \/]([\w.]+)/.exec(ua) || []; + var platform_match = /(ipad)/.exec(ua) || /(ipod)/.exec(ua) || /(windows phone)/.exec(ua) || /(iphone)/.exec(ua) || /(kindle)/.exec(ua) || /(android)/.exec(ua) || /(windows)/.exec(ua) || /(mac)/.exec(ua) || /(linux)/.exec(ua) || /(cros)/.exec(ua) || []; + var matched = { + browser: match[5] || match[3] || match[1] || '', + version: match[2] || match[4] || '0', + majorVersion: match[4] || match[2] || '0', + platform: platform_match[0] || '' + }; + var browser = {}; + if (matched.browser) { + browser[matched.browser] = true; + var versionArray = matched.majorVersion.split('.'); + browser.version = { + major: parseInt(matched.majorVersion, 10), + string: matched.version + }; + if (versionArray.length > 1) { + browser.version.minor = parseInt(versionArray[1], 10); + } + if (versionArray.length > 2) { + browser.version.build = parseInt(versionArray[2], 10); + } + } + if (matched.platform) { + browser[matched.platform] = true; + } + if (browser.chrome || browser.opr || browser.safari) { + browser.webkit = true; + } + if (browser.rv || browser.iemobile) { + if (browser.rv) { + delete browser.rv; + } + var msie = 'msie'; + matched.browser = msie; + browser[msie] = true; + } + if (browser.edge) { + delete browser.edge; + var msedge = 'msedge'; + matched.browser = msedge; + browser[msedge] = true; + } + if (browser.opr) { + var opera = 'opera'; + matched.browser = opera; + browser[opera] = true; + } + if (browser.safari && browser.android) { + var android = 'android'; + matched.browser = android; + browser[android] = true; + } + browser.name = matched.browser; + browser.platform = matched.platform; + for (var key in Browser) { + if (Browser.hasOwnProperty(key)) { + delete Browser[key]; + } + } + Object.assign(Browser, browser); + } + detect(); + exports.default = Browser; + }, {}], + 40: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _possibleConstructorReturn(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return call && (typeof call === "object" || typeof call === "function") ? call : self; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var RuntimeException = exports.RuntimeException = function() { + function RuntimeException(message) { + _classCallCheck(this, RuntimeException); + this._message = message; + } + _createClass(RuntimeException, [{ + key: 'toString', + value: function toString() { + return this.name + ': ' + this.message; + } + }, { + key: 'name', + get: function get() { + return 'RuntimeException'; + } + }, { + key: 'message', + get: function get() { + return this._message; + } + }]); + return RuntimeException; + }(); + var IllegalStateException = exports.IllegalStateException = function(_RuntimeException) { + _inherits(IllegalStateException, _RuntimeException); + + function IllegalStateException(message) { + _classCallCheck(this, IllegalStateException); + return _possibleConstructorReturn(this, (IllegalStateException.__proto__ || Object.getPrototypeOf(IllegalStateException)).call(this, message)); + } + _createClass(IllegalStateException, [{ + key: 'name', + get: function get() { + return 'IllegalStateException'; + } + }]); + return IllegalStateException; + }(RuntimeException); + var InvalidArgumentException = exports.InvalidArgumentException = function(_RuntimeException2) { + _inherits(InvalidArgumentException, _RuntimeException2); + + function InvalidArgumentException(message) { + _classCallCheck(this, InvalidArgumentException); + return _possibleConstructorReturn(this, (InvalidArgumentException.__proto__ || Object.getPrototypeOf(InvalidArgumentException)).call(this, message)); + } + _createClass(InvalidArgumentException, [{ + key: 'name', + get: function get() { + return 'InvalidArgumentException'; + } + }]); + return InvalidArgumentException; + }(RuntimeException); + var NotImplementedException = exports.NotImplementedException = function(_RuntimeException3) { + _inherits(NotImplementedException, _RuntimeException3); + + function NotImplementedException(message) { + _classCallCheck(this, NotImplementedException); + return _possibleConstructorReturn(this, (NotImplementedException.__proto__ || Object.getPrototypeOf(NotImplementedException)).call(this, message)); + } + _createClass(NotImplementedException, [{ + key: 'name', + get: function get() { + return 'NotImplementedException'; + } + }]); + return NotImplementedException; + }(RuntimeException); + }, {}], + 41: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var Log = function() { + function Log() { + _classCallCheck(this, Log); + } + _createClass(Log, null, [{ + key: 'e', + value: function e(tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = '[' + tag + '] > ' + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit('log', 'error', str); + } + if (!Log.ENABLE_ERROR) { + return; + } + if (console.error) { + console.error(str); + } else if (console.warn) { + console.warn(str); + } else { + console.log(str); + } + } + }, { + key: 'i', + value: function i(tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = '[' + tag + '] > ' + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit('log', 'info', str); + } + if (!Log.ENABLE_INFO) { + return; + } + if (console.info) { + console.info(str); + } else { + console.log(str); + } + } + }, { + key: 'w', + value: function w(tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = '[' + tag + '] > ' + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit('log', 'warn', str); + } + if (!Log.ENABLE_WARN) { + return; + } + if (console.warn) { + console.warn(str); + } else { + console.log(str); + } + } + }, { + key: 'd', + value: function d(tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = '[' + tag + '] > ' + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit('log', 'debug', str); + } + if (!Log.ENABLE_DEBUG) { + return; + } + if (console.debug) { + console.debug(str); + } else { + console.log(str); + } + } + }, { + key: 'v', + value: function v(tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = '[' + tag + '] > ' + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit('log', 'verbose', str); + } + if (!Log.ENABLE_VERBOSE) { + return; + } + console.log(str); + } + }]); + return Log; + }(); + Log.GLOBAL_TAG = 'flv.js'; + Log.FORCE_GLOBAL_TAG = false; + Log.ENABLE_ERROR = true; + Log.ENABLE_INFO = true; + Log.ENABLE_WARN = true; + Log.ENABLE_DEBUG = true; + Log.ENABLE_VERBOSE = true; + Log.ENABLE_CALLBACK = false; + Log.emitter = new _events2.default(); + exports.default = Log; + }, { + "events": 2 + }], + 42: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _events = _dereq_('events'); + var _events2 = _interopRequireDefault(_events); + var _logger = _dereq_('./logger.js'); + var _logger2 = _interopRequireDefault(_logger); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var LoggingControl = function() { + function LoggingControl() { + _classCallCheck(this, LoggingControl); + } + _createClass(LoggingControl, null, [{ + key: 'getConfig', + value: function getConfig() { + return { + globalTag: _logger2.default.GLOBAL_TAG, + forceGlobalTag: _logger2.default.FORCE_GLOBAL_TAG, + enableVerbose: _logger2.default.ENABLE_VERBOSE, + enableDebug: _logger2.default.ENABLE_DEBUG, + enableInfo: _logger2.default.ENABLE_INFO, + enableWarn: _logger2.default.ENABLE_WARN, + enableError: _logger2.default.ENABLE_ERROR, + enableCallback: _logger2.default.ENABLE_CALLBACK + }; + } + }, { + key: 'applyConfig', + value: function applyConfig(config) { + _logger2.default.GLOBAL_TAG = config.globalTag; + _logger2.default.FORCE_GLOBAL_TAG = config.forceGlobalTag; + _logger2.default.ENABLE_VERBOSE = config.enableVerbose; + _logger2.default.ENABLE_DEBUG = config.enableDebug; + _logger2.default.ENABLE_INFO = config.enableInfo; + _logger2.default.ENABLE_WARN = config.enableWarn; + _logger2.default.ENABLE_ERROR = config.enableError; + _logger2.default.ENABLE_CALLBACK = config.enableCallback; + } + }, { + key: '_notifyChange', + value: function _notifyChange() { + var emitter = LoggingControl.emitter; + if (emitter.listenerCount('change') > 0) { + var config = LoggingControl.getConfig(); + emitter.emit('change', config); + } + } + }, { + key: 'registerListener', + value: function registerListener(listener) { + LoggingControl.emitter.addListener('change', listener); + } + }, { + key: 'removeListener', + value: function removeListener(listener) { + LoggingControl.emitter.removeListener('change', listener); + } + }, { + key: 'addLogListener', + value: function addLogListener(listener) { + _logger2.default.emitter.addListener('log', listener); + if (_logger2.default.emitter.listenerCount('log') > 0) { + _logger2.default.ENABLE_CALLBACK = true; + LoggingControl._notifyChange(); + } + } + }, { + key: 'removeLogListener', + value: function removeLogListener(listener) { + _logger2.default.emitter.removeListener('log', listener); + if (_logger2.default.emitter.listenerCount('log') === 0) { + _logger2.default.ENABLE_CALLBACK = false; + LoggingControl._notifyChange(); + } + } + }, { + key: 'forceGlobalTag', + get: function get() { + return _logger2.default.FORCE_GLOBAL_TAG; + }, + set: function set(enable) { + _logger2.default.FORCE_GLOBAL_TAG = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'globalTag', + get: function get() { + return _logger2.default.GLOBAL_TAG; + }, + set: function set(tag) { + _logger2.default.GLOBAL_TAG = tag; + LoggingControl._notifyChange(); + } + }, { + key: 'enableAll', + get: function get() { + return _logger2.default.ENABLE_VERBOSE && _logger2.default.ENABLE_DEBUG && _logger2.default.ENABLE_INFO && _logger2.default.ENABLE_WARN && _logger2.default.ENABLE_ERROR; + }, + set: function set(enable) { + _logger2.default.ENABLE_VERBOSE = enable; + _logger2.default.ENABLE_DEBUG = enable; + _logger2.default.ENABLE_INFO = enable; + _logger2.default.ENABLE_WARN = enable; + _logger2.default.ENABLE_ERROR = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'enableDebug', + get: function get() { + return _logger2.default.ENABLE_DEBUG; + }, + set: function set(enable) { + _logger2.default.ENABLE_DEBUG = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'enableVerbose', + get: function get() { + return _logger2.default.ENABLE_VERBOSE; + }, + set: function set(enable) { + _logger2.default.ENABLE_VERBOSE = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'enableInfo', + get: function get() { + return _logger2.default.ENABLE_INFO; + }, + set: function set(enable) { + _logger2.default.ENABLE_INFO = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'enableWarn', + get: function get() { + return _logger2.default.ENABLE_WARN; + }, + set: function set(enable) { + _logger2.default.ENABLE_WARN = enable; + LoggingControl._notifyChange(); + } + }, { + key: 'enableError', + get: function get() { + return _logger2.default.ENABLE_ERROR; + }, + set: function set(enable) { + _logger2.default.ENABLE_ERROR = enable; + LoggingControl._notifyChange(); + } + }]); + return LoggingControl; + }(); + LoggingControl.emitter = new _events2.default(); + exports.default = LoggingControl; + }, { + "./logger.js": 41, + "events": 2 + }], + 43: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var Polyfill = function() { + function Polyfill() { + _classCallCheck(this, Polyfill); + } + _createClass(Polyfill, null, [{ + key: 'install', + value: function install() { + Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) { + obj.__proto__ = proto; + return obj; + }; + Object.assign = Object.assign || function(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + var output = Object(target); + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + if (source !== undefined && source !== null) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + output[key] = source[key]; + } + } + } + } + return output; + }; + if (typeof self.Promise !== 'function') { + _dereq_('es6-promise').polyfill(); + } + } + }]); + return Polyfill; + }(); + Polyfill.install(); + exports.default = Polyfill; + }, { + "es6-promise": 1 + }], + 44: [function(_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function checkContinuation(uint8array, start, checkLength) { + var array = uint8array; + if (start + checkLength < array.length) { + while (checkLength--) { + if ((array[++start] & 0xC0) !== 0x80) return false; + } + return true; + } else { + return false; + } + } + + function decodeUTF8(uint8array) { + var out = []; + var input = uint8array; + var i = 0; + var length = uint8array.length; + while (i < length) { + if (input[i] < 0x80) { + out.push(String.fromCharCode(input[i])); + ++i; + continue; + } else if (input[i] < 0xC0) {} else if (input[i] < 0xE0) { + if (checkContinuation(input, i, 1)) { + var ucs4 = (input[i] & 0x1F) << 6 | input[i + 1] & 0x3F; + if (ucs4 >= 0x80) { + out.push(String.fromCharCode(ucs4 & 0xFFFF)); + i += 2; + continue; + } + } + } else if (input[i] < 0xF0) { + if (checkContinuation(input, i, 2)) { + var _ucs = (input[i] & 0xF) << 12 | (input[i + 1] & 0x3F) << 6 | input[i + 2] & 0x3F; + if (_ucs >= 0x800 && (_ucs & 0xF800) !== 0xD800) { + out.push(String.fromCharCode(_ucs & 0xFFFF)); + i += 3; + continue; + } + } + } else if (input[i] < 0xF8) { + if (checkContinuation(input, i, 3)) { + var _ucs2 = (input[i] & 0x7) << 18 | (input[i + 1] & 0x3F) << 12 | (input[i + 2] & 0x3F) << 6 | input[i + 3] & 0x3F; + if (_ucs2 > 0x10000 && _ucs2 < 0x110000) { + _ucs2 -= 0x10000; + out.push(String.fromCharCode(_ucs2 >>> 10 | 0xD800)); + out.push(String.fromCharCode(_ucs2 & 0x3FF | 0xDC00)); + i += 4; + continue; + } + } + } + out.push(String.fromCharCode(0xFFFD)); + ++i; + } + return out.join(''); + } + exports.default = decodeUTF8; + }, {}] + }, {}, [21])(21) +}); \ No newline at end of file diff --git a/public/js/liveGame.js b/public/js/liveGame.js new file mode 100644 index 0000000..f194853 --- /dev/null +++ b/public/js/liveGame.js @@ -0,0 +1,63 @@ +var socket = new WebSocket("ws://10.0.0.195:8085"); + +socket.onopen = function(event) { + console.log("Connected to socket"); + socket.send(`{"clientPing": "ping"}`); +} + +socket.onmessage = function(event) { + var data = JSON.parse(event.data); + + try { + if (data.type == "question") { + console.log("Question received"); + document.getElementsByClassName('questionWindow')[0].style.display = 'block'; + + document.getElementById('questionText').innerHTML = data.question; + console.log(data); + + document.getElementById('questionCount').textContent = `${data.currentQuestion}/${data.totalQuestionCount}`; + + var totalTime = data.totalTimeMs / 1000; + document.getElementsByClassName('countdown')[0].style.display = 'block'; + document.getElementsByClassName('countdown')[0].style.animation = `countdownTimer ${totalTime}s`; + + if (data.question.length > 500) { + document.getElementById('questionText').innerHTML = data.question.substring(0, 500) + "..."; + } + + console.log(totalTime); + + setTimeout(function() { + document.getElementById('gameIcon').src = '/assets/live-games/logo-norm.png'; + document.getElementById('questionCount').textContent = `Time is up!`; + document.getElementsByClassName('countdown')[0].style.display = 'none'; + setTimeout(function() { + document.getElementsByClassName('countdown')[0].style.display = 'none'; + document.getElementsByClassName('questionWindow')[0].style.display = 'none'; + }, 2000); + }, totalTime * 1000); + } + + if (data.type == "broadcastStats") { + let viewStats = document.getElementById('viewCount'); + + //convert data.viewerCounts.connected to K, M, B + let viewCount = data.viewerCounts.connected; + if (viewCount >= 1000) { + viewCount = (viewCount / 1000).toFixed(1) + "K"; + } + if (viewCount >= 1000000) { + viewCount = (viewCount / 1000000).toFixed(1) + "M"; + } + if (viewCount >= 1000000000) { + viewCount = (viewCount / 1000000000).toFixed(1) + "B"; + } + + document.getElementById('viewCount').textContent = viewCount; + } + + } catch (e) { + console.log(e); + } +} \ No newline at end of file diff --git a/public/js/schedule/api.js b/public/js/schedule/api.js new file mode 100644 index 0000000..7fe45af --- /dev/null +++ b/public/js/schedule/api.js @@ -0,0 +1,104 @@ +let gameStatus = document.getElementById('nextGameInfo'); + +function getScheduleInfo() { + fetch('/api/schedule') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + console.log(data); + let schedule = data + + if (schedule.isWinnerTakeAll) { + nextGameText.textContent = `Next Game ${schedule.display.title}`; + nextGameText.innerHTML = nextGameText.innerHTML.replace(schedule.display.title, `${schedule.display.title} Winner Take All `); + } else if (schedule.isTestGame) { + nextGameText.textContent = `Next Game ${schedule.display.title}`; + nextGameText.innerHTML = nextGameText.innerHTML.replace(schedule.display.title, `Is Set to Development Mode`); + } else { + nextGameText.textContent = `Next Game ${schedule.display.title}`; + nextGameText.innerHTML = nextGameText.innerHTML.replace(schedule.display.title, `${schedule.display.title} `); + } + + let startTime = new Date(schedule.startTime); + let today = new Date(); + let tomorrow = new Date(today.getTime() + (24 * 60 * 60 * 1000)); + let nextWeek = new Date(today.getTime() + (7 * 24 * 60 * 60 * 1000)); + let startTimeString = ''; + if (startTime.getTime() < tomorrow.getTime()) { + startTimeString = `Today ${startTime.toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true })}`; + } else if (startTime.getTime() < nextWeek.getTime()) { + startTimeString = `Tomorrow ${startTime.toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true })}`; + } else { + startTimeString = `${startTime.toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true })}`; + } + if (schedule.startTime == null || schedule.startTime == undefined) { + gameStatus.textContent = "No Game Scheduled"; + } + + var num = schedule.prizeCents + num /= 100; + num.toLocaleString("en-US", { + style: "currency", + currency: schedule.currency + }); + + if (schedule.prizeCents && schedule.prizePoints) { + gameStatus.textContent = `${startTimeString} $${num} + ${schedule.prizePoints}pts`; + } else if (schedule.prizeCents) { + gameStatus.textContent = `${startTimeString} $${num}`; + } else if (schedule.prizePoints) { + gameStatus.textContent = `${startTimeString} ${schedule.prizePoints}pts`; + } else if (schedule.startTime) { + gameStatus.textContent = `${startTimeString}`; + } + if (schedule.isActive && schedule.prizeCents && schedule.prizePoints) { + if (schedule.prizePoints == 1) { + gameStatus.textContent = `We're live! $${num} + ${schedule.prizePoints}pt` + } else { + gameStatus.textContent = `We're live! $${num} + ${schedule.prizePoints}pts` + } + } else if (schedule.isActive && schedule.prizeCents == 0) { + if (schedule.prizePoints == 1) { + gameStatus.textContent = `We're live! ${schedule.prizePoints}pt`; + } else { + gameStatus.textContent = `We're live! ${schedule.prizePoints}pts`; + } + } else if (schedule.isActive && schedule.prizePoints == 0) { + gameStatus.textContent = `We're live! $${num}`; + } + if (schedule.isActive && schedule.prizeCents == 0 && schedule.prizePoints == 0) { + gameStatus.textContent = `We're live!`; + } + + if (schedule.isActive) { + let inviteBtn = document.getElementById('inviteBtn'); + inviteBtn.textContent = "Join Game"; + document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, -50%);'; + document.getElementsByClassName('liveGameView')[0].style.display = 'block'; + document.getElementsByClassName('liveGameView')[0].style.animation = 'debugPanelActive 0.5s'; + } else { + inviteBtn.textContent = "Invite for Extra Lives"; + //document.getElementsByClassName('liveGameView')[0].style.display = 'none'; + document.getElementsByClassName('liveGameView')[0].style.animation = 'debugPanelInactive 0.5s'; + document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, 50%)'; + } + + document.getElementById('gameLogo').src = schedule.display.logo; + + //Set the logo for live game + if (schedule.gameType == 'mjrules') { + document.getElementById('gameIcon').src = '/assets/live-games/logo-norm.png'; + } if (schedule.gameType == 'mjrules-sports') { + document.getElementById('gameIcon').src = '/assets/live-games/logo-sports.png'; + } + }) + .catch(function(err) { + console.log('Error: ' + err); + }); +} + +window.onload = function() { + getScheduleInfo(); + setInterval(getScheduleInfo, 5000); +} \ No newline at end of file diff --git a/public/js/schedule/config.js b/public/js/schedule/config.js new file mode 100644 index 0000000..5e50935 --- /dev/null +++ b/public/js/schedule/config.js @@ -0,0 +1,39 @@ +let nextGameText = document.getElementById('nextGameText'); + +fetch('/api/config') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + console.log(data); + let config = data + + /*let inviteBtn = document.getElementById('inviteBtn'); + inviteBtn.textContent = config.schedule.invite.btnText;*/ + + document.title = config.applicationInfo.name; + + (function() { + var link = document.querySelector("link[rel*='icon']") || document.createElement('link'); + link.type = 'image/x-icon'; + link.rel = 'shortcut icon'; + link.href = config.applicationInfo.icon; + document.getElementsByTagName('head')[0].appendChild(link); + })(); + + //nextGameText.innerHTML = config.schedule.nextGameText; + + if (config.schedule.invite.enabled) { + document.getElementsByClassName('startbtn')[0].style.visibility = 'block'; + console.log('invite enabled'); + } else { + document.getElementsByClassName('startbtn')[0].style.visibility = 'hidden'; + console.log('invite disabled'); + } + + if (config.schedule.bgAnimation == false) { + //sportsBg is a random name given so that no animation is applied + document.body.style.animationName = 'sportsBg'; + document.body.style.backgroundColor = 'hsl(280, 45%, 58%)'; + } + }) \ No newline at end of file diff --git a/public/js/schedule/debug.js b/public/js/schedule/debug.js new file mode 100644 index 0000000..9577feb --- /dev/null +++ b/public/js/schedule/debug.js @@ -0,0 +1,14 @@ + //listen to shake event + var shakeEvent = new Shake({threshold: 15}); + shakeEvent.start(); + window.addEventListener('shake', function(){ + alert("Shaked"); + }, false); + + //stop listening + function stopShake(){ + shakeEvent.stop(); + } + + //check if shake is supported or not. + if(!("ondevicemotion" in window)){alert("Not Supported");} \ No newline at end of file diff --git a/public/js/schedule/player.js b/public/js/schedule/player.js new file mode 100644 index 0000000..0b60405 --- /dev/null +++ b/public/js/schedule/player.js @@ -0,0 +1,11 @@ +if (flvjs.isSupported()) { + var videoElement = document.getElementById('videoElement'); + var flvPlayer = flvjs.createPlayer({ + type: 'flv', + url: 'http://10.0.0.195:8000/live/STREAM_NAME.flv' + }); + flvPlayer.attachMediaElement(videoElement); + flvPlayer.load(); + flvPlayer.play(); + document.getElementsByTagName('video')[0].play(); +} \ No newline at end of file diff --git a/public/serviceWorker.js b/public/js/serviceWorker.js similarity index 100% rename from public/serviceWorker.js rename to public/js/serviceWorker.js diff --git a/server.js b/server.js index a7652f3..b87e277 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,8 @@ const express = require('express') const fs = require('fs') +//Remove when pushed to production +/**/const WebSocket = require('ws'); +/**/const wss = new WebSocket.Server({ port: 8085 }); const app = express() // set the view engine to ejs @@ -18,6 +21,129 @@ app.get('/', function(req, res) { app.get('/api/schedule', function(req, res) { res.sendFile(__dirname + '/private/schedule.json'); }); + +app.get('/api/config', function(req, res) { + res.sendFile(__dirname + '/private/config.json'); +}); + +app.get('/api/users/me', function(req, res) { + res.sendFile(__dirname + '/private/me.json'); +}); + +app.get('/api/leaderboard', function(req, res) { + res.sendFile(__dirname + '/private/leaderboard.json'); +}); app.listen(8080); - console.log('Server is listening on port 8080'); \ No newline at end of file + console.log('Server is listening on port 8080'); + + //Got lazy and didn't want to mess with a secondary server via a diffrent file + //So I decided to add the socket to this file + + + wss.broadcast = function broadcast(data) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data); + //console.log(data); + } + }); + }; + + wss.on('connection', (ws) => { + ws.on('message', (data) => { + //console.log('data received \n ' + data) + wss.clients.forEach(function(client) { + client.send(data.toString()); + }); + }) + }) + + wss.broadcast = function broadcast(data) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data); + //console.log(data); + } + }); + }; + + wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + var msg = JSON.parse(message); + try { + if (msg.type == "question") { + incrementSeconds(); + wss.broadcast(JSON.stringify({ + type: "question", + question: msg.text.toString(), + totalQuestionCount: 12, + currentQuestion: 5, + isPrizeQuestion: false, + totalTimeMs: msg.totalTimeMs, + totalTimeLeftMs: msg.totalTimeMs, + ts: new Date().toISOString(), + c: 1 + })); + } + } + catch (e) { + console.log(e); + } + }); +}); + + wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + //console.log('received: %s', message); + var msg = JSON.parse(message); + if (msg.type == "prizeReveal") { + wss.broadcast(JSON.stringify({ + type: "dynamicPotAnimation", + ts: isoDate, + currency: msg.prizeInfo.currency, + currentPrizeCents: Math.floor(parseFloat(msg.prizeInfo.prizeStr.replace("$", "").replace(",", "")) * 100), + currentPrizePoints: 0, + sent: isoDate, + c: 1 + })); + } + }); + }); + + + var seconds = 0; + + function incrementSeconds() { + seconds += Math.floor(Math.random() * 734) + 1;; + //console.log(seconds); + } + + var cancel = setInterval(incrementSeconds, 2000); + + function broadcastStats() { + + let counter = 1; + while (counter <= 10) { + //console.log(counter); + counter++; + } + + wss.broadcast(JSON.stringify({ + type: "broadcastStats", + ts: Date.now(), + statusMessage: "", + viewerCounts: { + connected: wss.clients.size, + playing: wss.clients.size, + watching: 0, + }, + c: 1, + sent: Date.now() + })); + } + setInterval(broadcastStats, 5000); + + wss.on('error', function(error) { + console.log(error); +}); \ No newline at end of file diff --git a/socket/showToast.json b/socket/showToast.json new file mode 100644 index 0000000..582e3ac --- /dev/null +++ b/socket/showToast.json @@ -0,0 +1,5 @@ +{ + "type": "showToast", + "icon": "", + "text": "Sending friend request..." +} \ No newline at end of file diff --git a/socket/startLottoReveal.json b/socket/startLottoReveal.json new file mode 100644 index 0000000..3e0cfbb --- /dev/null +++ b/socket/startLottoReveal.json @@ -0,0 +1,8 @@ +{ + "type": "lotteryDraw", + "title": "Majority Rules Pick 4", + "lotteryId": "10001", + "dateOfDraw": "2018-01-01", + "totalDrawNumbers": [1,2,3,4], + "fullScreenDisplay": false +} \ No newline at end of file diff --git a/socket/startRound.json b/socket/startRound.json new file mode 100644 index 0000000..e6045aa --- /dev/null +++ b/socket/startRound.json @@ -0,0 +1,5 @@ +{ + "type": "question", + "text": "", + "totalTimeMs": 10000 +} \ No newline at end of file diff --git a/views/home.ejs b/views/home.ejs index ebe70a3..3c509e8 100644 --- a/views/home.ejs +++ b/views/home.ejs @@ -6,7 +6,7 @@ - Hello World + @@ -23,109 +23,47 @@ - +
-
invite for extra lives
- - +
+ + +
+ +
+ + 0 +
+ + + + + +
+
+
Question Text Goes Here
+
+ +
+
+ +
+ +
Toast Text Goes Here
+
+ + + + + + + + + \ No newline at end of file From 9a4ed19fca4bc151b513502c2e0b9b97d662c0bd Mon Sep 17 00:00:00 2001 From: Alan Michaelsen Date: Fri, 25 Feb 2022 05:20:54 -0500 Subject: [PATCH 3/4] Currency update Fixed an issue where the schedule currency wouldn't correspond to the set value in the schedule json file Co-Authored-By: atlanf586 <66658570+atlanf586@users.noreply.github.com> --- package-lock.json | 11 +++++++ package.json | 1 + private/config.json | 8 +++++ private/schedule.json | 10 +++---- public/css/liveGame.css | 15 ++++++++-- public/js/liveGame.js | 55 +++++++++++++++++++++++++++++++++-- public/js/notifications.js | 5 ++++ public/js/schedule/api.js | 32 ++++++++++++-------- public/js/schedule/config.js | 13 +++++++++ public/js/schedule/player.js | 11 ------- server.js | 40 +++++++++++++++++++++++++ socket/broadcastSnapshot.json | 26 +++++++++++++++++ socket/gameStatus.json | 8 +++++ socket/showToast.json | 4 +-- views/home.ejs | 5 ++-- 15 files changed, 206 insertions(+), 38 deletions(-) create mode 100644 public/js/notifications.js delete mode 100644 public/js/schedule/player.js create mode 100644 socket/broadcastSnapshot.json create mode 100644 socket/gameStatus.json diff --git a/package-lock.json b/package-lock.json index 969cda6..da6cab0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "dollars-to-cents": "^1.0.3", "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", @@ -468,6 +469,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "node_modules/dollars-to-cents": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dollars-to-cents/-/dollars-to-cents-1.0.3.tgz", + "integrity": "sha1-k1hUpvsbZV15QjwuVLU9Xnyvixs=" + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -2515,6 +2521,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "dollars-to-cents": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dollars-to-cents/-/dollars-to-cents-1.0.3.tgz", + "integrity": "sha1-k1hUpvsbZV15QjwuVLU9Xnyvixs=" + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", diff --git a/package.json b/package.json index 706a710..2144373 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/LeoBadeaux/majorityrules#readme", "dependencies": { + "dollars-to-cents": "^1.0.3", "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", diff --git a/private/config.json b/private/config.json index 55223f6..0e9db55 100644 --- a/private/config.json +++ b/private/config.json @@ -18,6 +18,14 @@ "rewardType": "life" } }, + "liveGame": { + "chat": { + "enabled": false, + "interval": 5000, + "maxMsgPerInterval": 5, + "chatWarningMsg": "Please wait ${interval} seconds before sending another message" + } + }, "notification": { "enabled": true, "allowInBackground": true, diff --git a/private/schedule.json b/private/schedule.json index 8a61ce4..4166e4c 100644 --- a/private/schedule.json +++ b/private/schedule.json @@ -1,11 +1,11 @@ { - "isActive": true, - "gameType": "mjrules", + "isActive": false, + "gameType": "mjrules-sports", "isTestGame": false, - "isWinnerTakeAll": false, + "isWinnerTakeAll": true, "startTime": "2022-02-13T20:00:00.000Z", - "prizeCents": 0, - "prizePoints": 5000, + "prizeCents": 10000, + "prizePoints": 0, "currency": "USD", "display": { "title": "Majority Rules", diff --git a/public/css/liveGame.css b/public/css/liveGame.css index 9d3d74a..cdebb5a 100644 --- a/public/css/liveGame.css +++ b/public/css/liveGame.css @@ -84,14 +84,14 @@ } .toastWindow .toastText { - color: rgb(0, 0, 0); + color: black; font-family: 'Roboto', sans-serif; font-size: 20px; width: 80%; position: absolute; - top: 28%; + top: 50%; left: 50%; - transform: translate(-50%, 0px); + transform: translate(-50%, -50%); text-align: center; } @@ -106,6 +106,15 @@ } } +@keyframes toastRemove { + 0% { + bottom: 30px; + } + 100% { + bottom: -180px; + } +} + /*Debug Panel Animations*/ @keyframes debugPanelActive { diff --git a/public/js/liveGame.js b/public/js/liveGame.js index f194853..2afb42d 100644 --- a/public/js/liveGame.js +++ b/public/js/liveGame.js @@ -1,4 +1,5 @@ -var socket = new WebSocket("ws://10.0.0.195:8085"); +var socket = new WebSocket(`ws://${window.location.hostname}:8085`); +console.log(`ws://${window.location.hostname}:8085`); socket.onopen = function(event) { console.log("Connected to socket"); @@ -9,6 +10,15 @@ socket.onmessage = function(event) { var data = JSON.parse(event.data); try { + + if (data.type == "gameStatus") { + if (data.playingState == "eliminated") { + document.getElementsByClassName("questionWindow")[0].style.backgroundColor = "rgb(255, 0, 85)"; + } else { + document.getElementsByClassName("questionWindow")[0].style.backgroundColor = "rgb(255, 136, 0)"; + } + } + if (data.type == "question") { console.log("Question received"); document.getElementsByClassName('questionWindow')[0].style.display = 'block'; @@ -42,7 +52,6 @@ socket.onmessage = function(event) { if (data.type == "broadcastStats") { let viewStats = document.getElementById('viewCount'); - //convert data.viewerCounts.connected to K, M, B let viewCount = data.viewerCounts.connected; if (viewCount >= 1000) { viewCount = (viewCount / 1000).toFixed(1) + "K"; @@ -57,6 +66,48 @@ socket.onmessage = function(event) { document.getElementById('viewCount').textContent = viewCount; } + //Toast messages + if (data.type == "showToast") { + document.getElementsByClassName('toastWindow')[0].style.display = 'block'; + var toastMessage = data.text; + + var boldedText = toastMessage.split("*"); + var boldedTextHtml = ""; + for (var i = 0; i < boldedText.length; i++) { + if (i % 2 == 0) { + boldedTextHtml += boldedText[i]; + } else { + boldedTextHtml += `${boldedText[i]}`; + } + + if (toastMessage.length > 100) { + toastMessage = toastMessage.substring(0, toastMessage.length - 1); + toastMessage += "..."; + } + + document.getElementById('toastText').innerHTML = boldedTextHtml; + document.getElementById('toastIcon').src = data.icon; + + document.getElementById('toastIcon').style.width = `${document.getElementsByClassName('toastWindow')[0].offsetWidth * 0.25}px`; + + } + document.getElementById('toastText').innerHTML = boldedTextHtml; + + document.getElementsByClassName('toastWindow')[0].style.backgroundColor = 'white'; + + setTimeout(function() { + document.getElementsByClassName('toastWindow')[0].style.animation = 'toastRemove .5s'; + }, 10000); + + setTimeout(function() { + document.getElementsByClassName('toastWindow')[0].style.display = 'none'; + document.getElementsByClassName('toastWindow')[0].style.backgroundColor = 'rgba(0,0,0,0)'; + document.getElementsByClassName('toastWindow')[0].style.color = 'rgba(0,0,0,0)'; + document.getElementById('toastIcon').src = ''; + document.getElementsByClassName('toastWindow')[0].style.animation = 'none'; + }, 10500); + } + } catch (e) { console.log(e); } diff --git a/public/js/notifications.js b/public/js/notifications.js new file mode 100644 index 0000000..bcb3c35 --- /dev/null +++ b/public/js/notifications.js @@ -0,0 +1,5 @@ +/* + *notifications.js v1.0.0 + * Copyright (c) 2022, Alan Michaelsen, MobileMediaInteractions + * All rights reserved. +*/ \ No newline at end of file diff --git a/public/js/schedule/api.js b/public/js/schedule/api.js index 7fe45af..1932b6c 100644 --- a/public/js/schedule/api.js +++ b/public/js/schedule/api.js @@ -36,17 +36,12 @@ function getScheduleInfo() { gameStatus.textContent = "No Game Scheduled"; } - var num = schedule.prizeCents - num /= 100; - num.toLocaleString("en-US", { - style: "currency", - currency: schedule.currency - }); + let gamePrizeCents = (schedule.prizeCents/100).toLocaleString('en-US', { style: 'currency', currency: schedule.currency }) if (schedule.prizeCents && schedule.prizePoints) { - gameStatus.textContent = `${startTimeString} $${num} + ${schedule.prizePoints}pts`; + gameStatus.textContent = `${startTimeString} ${gamePrizeCents} + ${schedule.prizePoints}pts`; } else if (schedule.prizeCents) { - gameStatus.textContent = `${startTimeString} $${num}`; + gameStatus.textContent = `${startTimeString} ${gamePrizeCents}`; } else if (schedule.prizePoints) { gameStatus.textContent = `${startTimeString} ${schedule.prizePoints}pts`; } else if (schedule.startTime) { @@ -54,9 +49,9 @@ function getScheduleInfo() { } if (schedule.isActive && schedule.prizeCents && schedule.prizePoints) { if (schedule.prizePoints == 1) { - gameStatus.textContent = `We're live! $${num} + ${schedule.prizePoints}pt` + gameStatus.textContent = `We're live! ${gamePrizeCents} + ${schedule.prizePoints}pt` } else { - gameStatus.textContent = `We're live! $${num} + ${schedule.prizePoints}pts` + gameStatus.textContent = `We're live! ${gamePrizeCents} + ${schedule.prizePoints}pts` } } else if (schedule.isActive && schedule.prizeCents == 0) { if (schedule.prizePoints == 1) { @@ -65,7 +60,7 @@ function getScheduleInfo() { gameStatus.textContent = `We're live! ${schedule.prizePoints}pts`; } } else if (schedule.isActive && schedule.prizePoints == 0) { - gameStatus.textContent = `We're live! $${num}`; + gameStatus.textContent = `We're live! ${gamePrizeCents}`; } if (schedule.isActive && schedule.prizeCents == 0 && schedule.prizePoints == 0) { gameStatus.textContent = `We're live!`; @@ -86,12 +81,25 @@ function getScheduleInfo() { document.getElementById('gameLogo').src = schedule.display.logo; - //Set the logo for live game if (schedule.gameType == 'mjrules') { document.getElementById('gameIcon').src = '/assets/live-games/logo-norm.png'; } if (schedule.gameType == 'mjrules-sports') { document.getElementById('gameIcon').src = '/assets/live-games/logo-sports.png'; } + + if (schedule.isActive) { + //This code will set the url for the stream + if (flvjs.isSupported()) { + var videoElement = document.getElementById('videoElement'); + var flvPlayer = flvjs.createPlayer({ + type: 'flv', + url: schedule.live.flv + }); + flvPlayer.attachMediaElement(videoElement); + flvPlayer.load(); + flvPlayer.play(); + } + } }) .catch(function(err) { console.log('Error: ' + err); diff --git a/public/js/schedule/config.js b/public/js/schedule/config.js index 5e50935..43bd431 100644 --- a/public/js/schedule/config.js +++ b/public/js/schedule/config.js @@ -36,4 +36,17 @@ fetch('/api/config') document.body.style.animationName = 'sportsBg'; document.body.style.backgroundColor = 'hsl(280, 45%, 58%)'; } + + //Chat Configuration + + if (config.liveGame.chat.enabled) { + console.log('chat enabled'); + } else { + var interval = config.liveGame.chat.interval / 1000; + + if (config.liveGame.chat.chatWarningMsg.includes('${interval}')) { + config.liveGame.chat.chatWarningMsg = config.liveGame.chat.chatWarningMsg.replace('${interval}', interval + 's'); + console.log(config.liveGame.chat.chatWarningMsg); + } + } }) \ No newline at end of file diff --git a/public/js/schedule/player.js b/public/js/schedule/player.js deleted file mode 100644 index 0b60405..0000000 --- a/public/js/schedule/player.js +++ /dev/null @@ -1,11 +0,0 @@ -if (flvjs.isSupported()) { - var videoElement = document.getElementById('videoElement'); - var flvPlayer = flvjs.createPlayer({ - type: 'flv', - url: 'http://10.0.0.195:8000/live/STREAM_NAME.flv' - }); - flvPlayer.attachMediaElement(videoElement); - flvPlayer.load(); - flvPlayer.play(); - document.getElementsByTagName('video')[0].play(); -} \ No newline at end of file diff --git a/server.js b/server.js index b87e277..1c5cb00 100644 --- a/server.js +++ b/server.js @@ -67,6 +67,46 @@ app.get('/api/leaderboard', function(req, res) { } }); }; + + //when a client connects, console.log a message + wss.on('connection', function connection(ws) { + + fs.readFile(__dirname + '/private/schedule.json', 'utf8', function (err, data) { + if (err) throw err; + var schedule = JSON.parse(data); + + wss.broadcast(JSON.stringify({ + type: "gameStatus", + prize: (schedule.prizeCents/100).toLocaleString('en-US', { style: 'currency', currency: schedule.currency }), + prizeCents: schedule.prizeCents, + prizePoints: schedule.prizePoints, + isWinnerTakeAll: schedule.isWinnerTakeAll, + playingState: "pregame", + questionInfo: { + current: 0, + total: 12, + }, + vipGameInfo: { + prizeCents: 0, + prizePoints: 0, + }, + extraLife: false, + eraser: false, + vip: false, + "ts": Date.now(), + })); + }); + }); + + wss.broadcast(JSON.stringify({ + "type": "gameStatus", + "prize": 0, + "prizeCents": 0, + "prizePoints": 0, + "playingState": "pregame", + "ts": Date.now(), + })); + wss.on('connection', function connection(ws) { ws.on('message', function incoming(message) { diff --git a/socket/broadcastSnapshot.json b/socket/broadcastSnapshot.json new file mode 100644 index 0000000..0474114 --- /dev/null +++ b/socket/broadcastSnapshot.json @@ -0,0 +1,26 @@ +{ + "type": "broadcastSnapshot", + "snapshotId": "snap-gid3456", + "broadcastStats": { + "prize": "$20", + "prizeCents": 2000, + "prizePoints": 20 + }, + "viewerStats": { + "playing": 1235, + "watching": 567, + "eliminated": 123 + }, + "question": { + "current": 0, + "total": 0, + "isPrizeQuestion": false, + "lastQuestionWithPrize": 0, + "prizePool": "$0", + "prizePoolCents": 0, + "prizePoolPoints": 0, + "usersTookPrizeFromQuestion": 0, + "rewardPerUsersStr": "$250", + "rewardPerUsersCents": 25000 + } +} \ No newline at end of file diff --git a/socket/gameStatus.json b/socket/gameStatus.json new file mode 100644 index 0000000..3b14ab4 --- /dev/null +++ b/socket/gameStatus.json @@ -0,0 +1,8 @@ +{ + "type": "gameStatus", + "prize": "$500", + "prizeCents": 500, + "prizePoints": 0, + "playingState": "pregame", + "ts": "1579098983" +} \ No newline at end of file diff --git a/socket/showToast.json b/socket/showToast.json index 582e3ac..b8959ea 100644 --- a/socket/showToast.json +++ b/socket/showToast.json @@ -1,5 +1,5 @@ { "type": "showToast", - "icon": "", - "text": "Sending friend request..." + "text": "Toast Text", + "icon": "" } \ No newline at end of file diff --git a/views/home.ejs b/views/home.ejs index 3c509e8..1774d3a 100644 --- a/views/home.ejs +++ b/views/home.ejs @@ -53,15 +53,14 @@
- +
Toast Text Goes Here
- - + From 7086032484d124fcbcd02554d3c2f1b52a62c22e Mon Sep 17 00:00:00 2001 From: Alan Michaelsen Date: Sun, 6 Mar 2022 04:34:59 -0500 Subject: [PATCH 4/4] admin Created a simple admin for sending questions to the socket, useable but unfinished --- .DS_Store | Bin 8196 -> 8196 bytes package-lock.json | 182 +++++++++++++++++++++++++++++++++++ package.json | 1 + private/adminConfig.json | 11 +++ private/config.json | 21 +--- private/schedule.json | 8 +- public/.DS_Store | Bin 6148 -> 6148 bytes public/assets/.DS_Store | Bin 8196 -> 8196 bytes public/js/.DS_Store | Bin 6148 -> 6148 bytes public/js/admin/config.js | 21 ++++ public/js/admin/main.js | 0 public/js/admin/socket.js | 14 +++ public/js/liveGame.js | 3 + public/js/schedule/api.js | 23 ++++- public/js/schedule/config.js | 19 +--- server.js | 8 ++ views/admin.ejs | 82 ++++++++++++++++ views/home.ejs | 3 +- 18 files changed, 352 insertions(+), 44 deletions(-) create mode 100644 private/adminConfig.json create mode 100644 public/js/admin/config.js create mode 100644 public/js/admin/main.js create mode 100644 public/js/admin/socket.js create mode 100644 views/admin.ejs diff --git a/.DS_Store b/.DS_Store index 73bfe14a340c9a06aa55adf3b3e3ed04fe48a6e4..58e80e783653a7dcfb1b094a8a7e208b8acdbfcd 100644 GIT binary patch delta 583 zcmZp1XmOa}&nUGqU^hRb)MOq3P3A9`U4XQVNN&E1OHxjL5(5JR$7%ttuisxDc7#f# zV3pu6$S@2}&d)6X>R@1OaF~2pK#_@+Yw|MzIks!MH+Q^$IoUu^WU`zf4}z=27%(|l z@H5jsiOC*9GHl7)9i=|JoSY>j2V?dLDKG|XUN6MY$i(6``GByD7SQnKq9=zPfixRK zF+)B>GD9{)Dnm(bKEhcLHIvyyfSM<(i)c^2Bh(;bYG9zFU}9lXtD{hDX#`>$n@uhd zHm+x7C}YS38d1(roRg050t16&G0-3+S>zzO7oJ`I78oSxDiDsqt^zrb7#I|Q+9i;! iC<`vi%gN762Z}RpEDUGb%r5bbWir2z%pi7U2onHtf}&6W delta 338 zcmZp1XmOa}&nU4mU^hRb#AF@;P3Ap@zCc<=Bsbs1B`GIAiGhKE!~c)4rOboFj!=md ztP=bM8HT~h`MCu^9Sn?I2PPjDP-J2`I{BG^9NVg?j%ViGoNOQ{GFeWL2fvZiV&FQxfI|40X zV<=|GXGmtqW=Lfy$<0SN3!-K+n}`CV!DMw2?Vy}=gwq%pc-8_nvoe%1WCAsoGZZ6x tb(!1_so)!6<55%~42P(gTqY{VB)~BFtc=0N3Ss8W>=NHtHde4R0{}jaW$*w1 diff --git a/package-lock.json b/package-lock.json index da6cab0..519abf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", + "node-media-server": "^2.3.8", "nodemon": "^2.0.12", "ws": "^8.5.0", "wss": "^3.3.4" @@ -142,6 +143,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -418,6 +424,14 @@ "node": ">=8" } }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1232,6 +1246,11 @@ "node": ">= 0.8.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -1368,6 +1387,95 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "optional": true }, + "node_modules/node-media-server": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/node-media-server/-/node-media-server-2.3.8.tgz", + "integrity": "sha512-IWji6X4RQHoiAu0mTojtQ7dznrdsHRahXG51d8um0bjFKkmtJHN3W9oA2fVtFtDrAYMC5bG9GvGDO2qdZtgzww==", + "dependencies": { + "basic-auth-connect": "^1.0.0", + "chalk": "^2.4.2", + "dateformat": "^3.0.3", + "express": "^4.16.4", + "lodash": ">=4.17.13", + "minimist": "^1.2.5", + "mkdirp": "1.0.3", + "ws": "^7.4.6" + }, + "bin": { + "node-media-server": "bin/app.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/node-media-server/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/node-media-server/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/node-media-server/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/node-media-server/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/node-media-server/node_modules/mkdirp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz", + "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-media-server/node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/nodemon": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", @@ -2270,6 +2378,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2479,6 +2592,11 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3103,6 +3221,11 @@ "type-check": "~0.3.2" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -3199,6 +3322,65 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "optional": true }, + "node-media-server": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/node-media-server/-/node-media-server-2.3.8.tgz", + "integrity": "sha512-IWji6X4RQHoiAu0mTojtQ7dznrdsHRahXG51d8um0bjFKkmtJHN3W9oA2fVtFtDrAYMC5bG9GvGDO2qdZtgzww==", + "requires": { + "basic-auth-connect": "^1.0.0", + "chalk": "^2.4.2", + "dateformat": "^3.0.3", + "express": "^4.16.4", + "lodash": ">=4.17.13", + "minimist": "^1.2.5", + "mkdirp": "1.0.3", + "ws": "^7.4.6" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "mkdirp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz", + "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==" + }, + "ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} + } + } + }, "nodemon": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", diff --git a/package.json b/package.json index 2144373..28f79ca 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "ejs": "^3.1.6", "express": "^4.17.1", "fs": "^0.0.1-security", + "node-media-server": "^2.3.8", "nodemon": "^2.0.12", "ws": "^8.5.0", "wss": "^3.3.4" diff --git a/private/adminConfig.json b/private/adminConfig.json new file mode 100644 index 0000000..ab68963 --- /dev/null +++ b/private/adminConfig.json @@ -0,0 +1,11 @@ +{ + "applicationInfo": { + "name": "Majority Rules", + "icon": "/assets/majorityrules2-512_x_512.png" + }, + "gameConfig": { + "maxPrizeCents": 0, + "maxPrizePoints": 1000, + "prizeQuestion": false + } +} \ No newline at end of file diff --git a/private/config.json b/private/config.json index 0e9db55..e99f3ab 100644 --- a/private/config.json +++ b/private/config.json @@ -9,27 +9,12 @@ "changeApiUrl": true }, "schedule": { - "scheduleType": "classic", - "nextGameText": "Next Game", "bgAnimation": true, "invite": { "enabled": true, - "btnText": "Invite for extra lives", - "rewardType": "life" + "btnText": "Invite for Extra Lives" } }, - "liveGame": { - "chat": { - "enabled": false, - "interval": 5000, - "maxMsgPerInterval": 5, - "chatWarningMsg": "Please wait ${interval} seconds before sending another message" - } - }, - "notification": { - "enabled": true, - "allowInBackground": true, - "requireAuthToReceive": false, - "provider": "onesignal" - } + "liveGame": {}, + "notification": {} } \ No newline at end of file diff --git a/private/schedule.json b/private/schedule.json index 4166e4c..9d776a6 100644 --- a/private/schedule.json +++ b/private/schedule.json @@ -1,8 +1,8 @@ { - "isActive": false, - "gameType": "mjrules-sports", + "isActive": true, + "gameType": "mjrules", "isTestGame": false, - "isWinnerTakeAll": true, + "isWinnerTakeAll": false, "startTime": "2022-02-13T20:00:00.000Z", "prizeCents": 10000, "prizePoints": 0, @@ -13,7 +13,7 @@ "logo": "/assets/logo.svg" }, "live": { - "flv": "", + "flv": "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8", "socketUrl": "" } } \ No newline at end of file diff --git a/public/.DS_Store b/public/.DS_Store index 2a4ffd0051f7457cf33dcaa61944d4385b1a6928..a21fe0811ba1fb4637526c9b96c0e676ccc1baca 100644 GIT binary patch delta 192 zcmZoMXffCz!>Yx=z|dUuYwS{q;lDJBJ+^7#P?X5*dntFqNT%p*S}`#U&{xKM5$#0Z}vAjWvu( z{L18ctYRv8ERX(Px&_w7%#aMyg{&STJNX8yQDE|6paDz_Ss(>2a04r&l9q)+EQQJ; fEJK$o$S@2}&d)6Xn!~`rdSPSX8ph4+9Dn%%h@w21 diff --git a/public/assets/.DS_Store b/public/assets/.DS_Store index 916b99173b8daed375ce71254682babe0b6cf431..e7611b4c7394db2a89042692d4d2f149cc062065 100644 GIT binary patch delta 77 zcmZp1XmQwJBFMqOz|dUu|JzwIB* diff --git a/public/js/.DS_Store b/public/js/.DS_Store index a2a7e0ef9e8561424bf2d74fac6f8e2a8965d33a..37eac0a5337382fa3dc7dbe9ed53f278e3679350 100644 GIT binary patch delta 259 zcmZoMXfc=|#>B!ku~2NHo}w@p0|Nsi1A_nqLtak0VQ_MOZo%e-%qyAeK@zMCi3}+W zxeS>INuVeYu!I2#B-z}27nh`*{3M_#hvbAGQtw|Lc0^Z^LO?}92E=-xJ|JLHV3=&c zEHYVv=^2yEULaF!vK%uP8&IaX=*eU~W+enuY;q1WACm)E{pJbG-x)WvbMSKjy$JNk Wcjn3bB90tDA2NYV-5epZh8X}2yFE$( delta 134 zcmZoMXfc=|#>B)qu~2NHo}vgF0|Nsi1A_nqLkdGFLk>e~QhD*l#1)K;Y?C*zicDU> z@{CFHB9JLIc^)el+vBu1dqeL`UdO70V2VwC!^+1LzyMOeS%B?3ZEC2V@b;<_M8B%m8alCqe)K diff --git a/public/js/admin/config.js b/public/js/admin/config.js new file mode 100644 index 0000000..2aafe4a --- /dev/null +++ b/public/js/admin/config.js @@ -0,0 +1,21 @@ +let nextGameText = document.getElementById('nextGameText'); + +fetch('/api/admin/config') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + console.log(data); + let config = data + + document.title = `${config.applicationInfo.name} | Admin`; + document.getElementById('navbar-brand').textContent = config.applicationInfo.name; + + (function() { + var link = document.querySelector("link[rel*='icon']") || document.createElement('link'); + link.type = 'image/x-icon'; + link.rel = 'shortcut icon'; + link.href = config.applicationInfo.icon; + document.getElementsByTagName('head')[0].appendChild(link); + })(); + }) \ No newline at end of file diff --git a/public/js/admin/main.js b/public/js/admin/main.js new file mode 100644 index 0000000..e69de29 diff --git a/public/js/admin/socket.js b/public/js/admin/socket.js new file mode 100644 index 0000000..c3c8b0b --- /dev/null +++ b/public/js/admin/socket.js @@ -0,0 +1,14 @@ +var socket = new WebSocket(`ws://${window.location.hostname}:8085`); + +socket.onopen = function(event) { + console.log("Connected to socket"); + socket.send(`{"clientPing": "ping"}`); +} + +document.getElementById("post-question-button").addEventListener("click", function() { + socket.send(JSON.stringify({ + "type": "question", + "text": document.getElementById("question-text").value, + "totalTimeMs": document.getElementById("question-time").value * 1000, + })); +}); \ No newline at end of file diff --git a/public/js/liveGame.js b/public/js/liveGame.js index 2afb42d..6ba527c 100644 --- a/public/js/liveGame.js +++ b/public/js/liveGame.js @@ -37,6 +37,9 @@ socket.onmessage = function(event) { } console.log(totalTime); + + var audio = new Audio('https://hqrelive.com/sounds/question-general.mp3'); + audio.play(); setTimeout(function() { document.getElementById('gameIcon').src = '/assets/live-games/logo-norm.png'; diff --git a/public/js/schedule/api.js b/public/js/schedule/api.js index 1932b6c..28d4d71 100644 --- a/public/js/schedule/api.js +++ b/public/js/schedule/api.js @@ -69,9 +69,9 @@ function getScheduleInfo() { if (schedule.isActive) { let inviteBtn = document.getElementById('inviteBtn'); inviteBtn.textContent = "Join Game"; - document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, -50%);'; + /*document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, -50%);'; document.getElementsByClassName('liveGameView')[0].style.display = 'block'; - document.getElementsByClassName('liveGameView')[0].style.animation = 'debugPanelActive 0.5s'; + document.getElementsByClassName('liveGameView')[0].style.animation = 'debugPanelActive 0.5s';*/ } else { inviteBtn.textContent = "Invite for Extra Lives"; //document.getElementsByClassName('liveGameView')[0].style.display = 'none'; @@ -79,6 +79,25 @@ function getScheduleInfo() { document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, 50%)'; } + function joinGameInviteBtn() { + //add an event listener to the inviteBtn class + let inviteBtn = document.getElementById('inviteBtn'); + //if the game is active, then show the inviteBtn + if (schedule.isActive) { + document.getElementsByClassName('liveGameView')[0].style.transform = 'translate(-50%, -50%);'; + document.getElementsByClassName('liveGameView')[0].style.display = 'block'; + document.getElementsByClassName('liveGameView')[0].style.animation = 'debugPanelActive 0.5s'; + } else { + console.log('game is not active'); + } + } + + //add an event listener to the startbtn class, run the function joinGameInviteBtn when clicked + let startBtn = document.getElementsByClassName('startbtn')[0]; + startBtn.addEventListener('click', joinGameInviteBtn); + + + document.getElementById('gameLogo').src = schedule.display.logo; if (schedule.gameType == 'mjrules') { diff --git a/public/js/schedule/config.js b/public/js/schedule/config.js index 43bd431..c38b8a0 100644 --- a/public/js/schedule/config.js +++ b/public/js/schedule/config.js @@ -8,9 +8,6 @@ fetch('/api/config') console.log(data); let config = data - /*let inviteBtn = document.getElementById('inviteBtn'); - inviteBtn.textContent = config.schedule.invite.btnText;*/ - document.title = config.applicationInfo.name; (function() { @@ -21,11 +18,10 @@ fetch('/api/config') document.getElementsByTagName('head')[0].appendChild(link); })(); - //nextGameText.innerHTML = config.schedule.nextGameText; - if (config.schedule.invite.enabled) { document.getElementsByClassName('startbtn')[0].style.visibility = 'block'; console.log('invite enabled'); + document.getElementById('inviteBtn').textContent = config.schedule.invite.btnText; } else { document.getElementsByClassName('startbtn')[0].style.visibility = 'hidden'; console.log('invite disabled'); @@ -36,17 +32,4 @@ fetch('/api/config') document.body.style.animationName = 'sportsBg'; document.body.style.backgroundColor = 'hsl(280, 45%, 58%)'; } - - //Chat Configuration - - if (config.liveGame.chat.enabled) { - console.log('chat enabled'); - } else { - var interval = config.liveGame.chat.interval / 1000; - - if (config.liveGame.chat.chatWarningMsg.includes('${interval}')) { - config.liveGame.chat.chatWarningMsg = config.liveGame.chat.chatWarningMsg.replace('${interval}', interval + 's'); - console.log(config.liveGame.chat.chatWarningMsg); - } - } }) \ No newline at end of file diff --git a/server.js b/server.js index 1c5cb00..ae057f8 100644 --- a/server.js +++ b/server.js @@ -17,6 +17,10 @@ app.get('/', function(req, res) { res.render('home'); }); +app.get('/admin', function(req, res) { + res.render('admin'); +}); + // Api Routes app.get('/api/schedule', function(req, res) { res.sendFile(__dirname + '/private/schedule.json'); @@ -26,6 +30,10 @@ app.get('/api/config', function(req, res) { res.sendFile(__dirname + '/private/config.json'); }); +app.get('/api/admin/config', function(req, res) { + res.sendFile(__dirname + '/private/adminConfig.json'); +}); + app.get('/api/users/me', function(req, res) { res.sendFile(__dirname + '/private/me.json'); }); diff --git a/views/admin.ejs b/views/admin.ejs new file mode 100644 index 0000000..0f04eb1 --- /dev/null +++ b/views/admin.ejs @@ -0,0 +1,82 @@ + + + + + + + Majority Rules | Admin + + + +
+

Admin Controls

+
+ Not Live +
+ + + +
+ + + + + + +
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/views/home.ejs b/views/home.ejs index 1774d3a..6f49bca 100644 --- a/views/home.ejs +++ b/views/home.ejs @@ -23,14 +23,13 @@ -
-
+