From 907e6bab287a61f160f2a3f6f942c44c325d96e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Fri, 17 May 2024 09:25:49 +0200 Subject: [PATCH] feat: Add getNonDefaultConfiguration (#6620) --- .github/ISSUE_TEMPLATE/bug_report.md | 5 +-- lib/player.js | 18 ++++++++++ lib/util/config_utils.js | 53 ++++++++++++++++++++++++++++ test/cast/cast_utils_unit.js | 1 + test/player_unit.js | 11 ++++++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3c5871b0ae..6c11c43532 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -58,8 +58,9 @@ assignees: '' **What configuration are you using? What is the output of `player.getConfiguration()`?** diff --git a/lib/player.js b/lib/player.js index 6389da2b4a..d2c23afef4 100644 --- a/lib/player.js +++ b/lib/player.js @@ -3596,6 +3596,24 @@ shaka.Player = class extends shaka.util.FakeEventTarget { return ret; } + /** + * Return a copy of the current non default configuration. Modifications of + * the returned value will not affect the Player's active configuration. + * You must call player.configure() to make changes. + * + * @return {!Object} + * @export + */ + getNonDefaultConfiguration() { + goog.asserts.assert(this.config_, 'Config must not be null!'); + + const ret = this.defaultConfig_(); + shaka.util.PlayerConfiguration.mergeConfigObjects( + ret, this.config_, this.defaultConfig_()); + return shaka.util.ConfigUtils.getDifferenceFromConfigObjects( + this.config_, this.defaultConfig_()); + } + /** * Return a reference to the current configuration. Modifications to the * returned value will affect the Player's active configuration. This method diff --git a/lib/util/config_utils.js b/lib/util/config_utils.js index b11ba6fbe8..bdb1eaa594 100644 --- a/lib/util/config_utils.js +++ b/lib/util/config_utils.js @@ -152,4 +152,57 @@ shaka.util.ConfigUtils = class { static referenceParametersAndReturn(parameters, returnValue) { return parameters && returnValue; } + + /** + * @param {!Object} object + * @param {!Object} base + * @return {!Object} + * @export + */ + static getDifferenceFromConfigObjects(object, base) { + const isObject = (obj) => { + return obj && typeof obj === 'object' && !Array.isArray(obj); + }; + + const isArrayEmpty = (array) => { + return Array.isArray(array) && array.length === 0; + }; + + const changes = (object, base) => { + return Object.fromEntries( + Object.entries(object).reduce((acc, [key, value]) => { + // eslint-disable-next-line no-prototype-builtins + if (!base.hasOwnProperty(key)) { + acc.push([key, value]); + } else if (isObject(value) && isObject(base[key])) { + const diff = changes(value, base[key]); + if (Object.keys(diff).length > 0 || !isObject(diff)) { + acc.push([key, diff]); + } + } else if (isArrayEmpty(value) && isArrayEmpty(base[key])) { + // Do nothing if both are empty arrays + } else if (value !== base[key]) { + acc.push([key, value]); + } + return acc; + }, [])); + }; + + const diff = changes(object, base); + + const removeEmpty = (obj) => { + for (const key of Object.keys(obj)) { + if (isObject(obj[key]) && Object.keys(obj[key]).length === 0) { + delete obj[key]; + } else if (isArrayEmpty(obj[key])) { + delete obj[key]; + } else if (isObject(obj[key])) { + removeEmpty(obj[key]); + } + } + }; + + removeEmpty(diff); + return diff; + } }; diff --git a/test/cast/cast_utils_unit.js b/test/cast/cast_utils_unit.js index 2c5e83dcef..d675ef87e3 100644 --- a/test/cast/cast_utils_unit.js +++ b/test/cast/cast_utils_unit.js @@ -30,6 +30,7 @@ describe('CastUtils', () => { 'releaseAllMutexes', // Very specific to the inner workings of the player. 'unloadAndSavePreload', 'preload', + 'getNonDefaultConfiguration', // Test helper methods (not @export'd) 'createDrmEngine', diff --git a/test/player_unit.js b/test/player_unit.js index 4d379e3c83..977f9ba5e1 100644 --- a/test/player_unit.js +++ b/test/player_unit.js @@ -753,6 +753,17 @@ describe('Player', () => { }); }); + it('getNonDefaultConfiguration', () => { + player.configure({ + drm: { + retryParameters: {backoffFactor: 5}, + }, + }); + const nonDefaultConfiguration = player.getNonDefaultConfiguration(); + const config = player.getConfiguration(); + expect(nonDefaultConfiguration).not.toBe(config); + }); + describe('configure', () => { it('overwrites defaults', () => { const defaultConfig = player.getConfiguration();