From c6d6e5d339c45a2c63db82fa488bb50c45a0aa44 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Wed, 1 May 2024 10:52:34 +0200 Subject: [PATCH] fix: mute incorrect (#195) * fix: Mute parsed from events #194 * feat: Created some RenderingControl extensions --- src/services/base-service.ts | 12 ++++- .../rendering-control.service.extension.ts | 47 ++++++++++++++++++- src/sonos-device.ts | 18 ++++--- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/services/base-service.ts b/src/services/base-service.ts index 9916c8c..0d69551 100644 --- a/src/services/base-service.ts +++ b/src/services/base-service.ts @@ -544,6 +544,15 @@ export default abstract class BaseService { } } + /** + * Parse a single event property + * + * @param {string} name The name of the property + * @param {unknown} originalValue The original value of the property + * @param {string} type The expected type of the property + * @memberof BaseService + * @remarks This method can be overridden in subclasses to handle special cases, like ChannelValue for Mute and Volume + */ protected ResolveEventPropertyValue(name: string, originalValue: unknown, type: string): unknown { if (typeof originalValue === 'string' && (originalValue.startsWith('<') || originalValue.startsWith('<'))) { if (name.endsWith('MetaData')) { @@ -573,10 +582,11 @@ export default abstract class BaseService { const keys = Object.keys(properties).filter((k) => inKeys.indexOf(k) > -1); keys.forEach((k) => { + const expectedType = properties[k]; const originalValue = input[k].val ?? input[k]; // validate that originalValue is not undefined or empty or is not an empty object if (originalValue === undefined || originalValue === '' || (typeof originalValue === 'object' && Object.keys(originalValue).length === 0)) return; - output[k] = this.ResolveEventPropertyValue(k, originalValue, properties[k]); + output[k] = this.ResolveEventPropertyValue(k, originalValue, expectedType); }); if (Object.keys(output).length === 0) { diff --git a/src/services/rendering-control.service.extension.ts b/src/services/rendering-control.service.extension.ts index fe34bb9..68e2554 100644 --- a/src/services/rendering-control.service.extension.ts +++ b/src/services/rendering-control.service.extension.ts @@ -6,7 +6,8 @@ export class RenderingControlService extends RenderingControlServiceBase { if (name === 'Mute') { const output = {} as ChannelValue; (originalValue as Array).forEach((v) => { - output[v.channel] = v.val === '1'; + // The new xml parser will return the value as a number, converting to boolean + output[v.channel] = v.val === 1; }); return output; } @@ -20,4 +21,48 @@ export class RenderingControlService extends RenderingControlServiceBase { } return super.ResolveEventPropertyValue(name, originalValue, type); } + + /** + * Get nightmode status of playbar. + * + * @returns {Promise} + * @memberof RenderingControlService + */ + public async GetNightMode(): Promise { + return (await this.GetEQ({ InstanceID: 0, EQType: 'NightMode' })).CurrentValue === 1; + } + + /** + * Turn on/off night mode, on your playbar. + * shortcut to .RenderingControlService.SetEQ({ InstanceID: 0, EQType: 'NightMode', DesiredValue: dialogLevel === true ? 1 : 0 }) + * + * @param {boolean} nightmode + * @returns {Promise} + * @memberof RenderingControlService + */ + public SetNightMode(nightmode: boolean): Promise { + return this.SetEQ({ InstanceID: 0, EQType: 'NightMode', DesiredValue: nightmode === true ? 1 : 0 }); + } + + /** + * Get Speech Enhancement status of playbar + * + * @returns {Promise} + * @memberof RenderingControlService + */ + public async GetSpeechEnhancement(): Promise { + return (await this.GetEQ({ InstanceID: 0, EQType: 'DialogLevel' })).CurrentValue === 1; + } + + /** + * Turn on/off speech enhancement, on your playbar, + * shortcut to .RenderingControlService.SetEQ({ InstanceID: 0, EQType: 'DialogLevel', DesiredValue: dialogLevel === true ? 1 : 0 }) + * + * @param {boolean} dialogLevel + * @returns {Promise} + * @memberof RenderingControlService + */ + public SetSpeechEnhancement(dialogLevel: boolean): Promise { + return this.SetEQ({ InstanceID: 0, EQType: 'DialogLevel', DesiredValue: dialogLevel === true ? 1 : 0 }); + } } diff --git a/src/sonos-device.ts b/src/sonos-device.ts index b13b36b..2b25ba3 100644 --- a/src/sonos-device.ts +++ b/src/sonos-device.ts @@ -1131,8 +1131,8 @@ export default class SonosDevice extends SonosDeviceBase { * @returns {Promise} * @memberof SonosDevice */ - public async GetNightMode(): Promise { - return (await this.RenderingControlService.GetEQ({ InstanceID: 0, EQType: 'NightMode' })).CurrentValue === 1; + public GetNightMode(): Promise { + return this.RenderingControlService.GetNightMode(); } /** @@ -1165,8 +1165,8 @@ export default class SonosDevice extends SonosDeviceBase { * @returns {Promise} * @memberof SonosDevice */ - public async GetSpeechEnhancement(): Promise { - return (await this.RenderingControlService.GetEQ({ InstanceID: 0, EQType: 'DialogLevel' })).CurrentValue === 1; + public GetSpeechEnhancement(): Promise { + return this.RenderingControlService.GetSpeechEnhancement(); } /** @@ -1254,9 +1254,8 @@ export default class SonosDevice extends SonosDeviceBase { * @returns {Promise} * @memberof SonosDevice */ - public async SetNightMode(nightmode: boolean): Promise { - return await this.RenderingControlService - .SetEQ({ InstanceID: 0, EQType: 'NightMode', DesiredValue: nightmode === true ? 1 : 0 }); + public SetNightMode(nightmode: boolean): Promise { + return this.RenderingControlService.SetNightMode(nightmode); } /** @@ -1319,9 +1318,8 @@ export default class SonosDevice extends SonosDeviceBase { * @returns {Promise} * @memberof SonosDevice */ - public async SetSpeechEnhancement(dialogLevel: boolean): Promise { - return await this.RenderingControlService - .SetEQ({ InstanceID: 0, EQType: 'DialogLevel', DesiredValue: dialogLevel === true ? 1 : 0 }); + public SetSpeechEnhancement(dialogLevel: boolean): Promise { + return this.RenderingControlService.SetSpeechEnhancement(dialogLevel); } /**