Skip to content

Commit cdb7667

Browse files
committed
[ 1.0.34 ] * Added card configuration option deviceDefaultId for specifying a Device ID to use for all SpotifyPlus service calls that require a deviceId argument. This allows you to hide the Devices section, and utilize the specific device for all service requests that require a deviceId.
* Added card configuration option `playerVolumeMaxValue` for specifying the maximum volume value allowed to be set via the card user-interface. This value does not apply if adjusting the volume via services or other media player UI's.
1 parent ea4ea56 commit cdb7667

File tree

10 files changed

+453
-37
lines changed

10 files changed

+453
-37
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Change are listed in reverse chronological order (newest to oldest).
66

77
<span class="changelog">
88

9+
###### [ 1.0.34 ] - 2025/01/26
10+
11+
* Added card configuration option `deviceDefaultId` for specifying a Device ID to use for all SpotifyPlus service calls that require a deviceId argument. This allows you to hide the Devices section, and utilize the specific device for all service requests that require a deviceId.
12+
* Added card configuration option `playerVolumeMaxValue` for specifying the maximum volume value allowed to be set via the card user-interface. This value does not apply if adjusting the volume via services or other media player UI's.
13+
914
###### [ 1.0.33 ] - 2025/01/23
1015

1116
* This release requires the SpotifyPlus Integration v1.0.86+ release; please make sure you update the SpotifyPlus integration prior to updating this SpotifyPlus Card release.

src/components/player-controls.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Store } from '../model/store';
2323
import { MediaPlayer } from '../model/media-player';
2424
import { MediaPlayerEntityFeature, MediaPlayerState, RepeatMode } from '../services/media-control-service';
2525
import { MediaControlService } from '../services/media-control-service';
26+
import { SpotifyPlusService } from '../services/spotifyplus-service';
2627
import { ProgressEndedEvent } from '../events/progress-ended';
2728
import { ProgressStartedEvent } from '../events/progress-started';
2829
import { closestElement, isCardInEditPreview } from '../utils/utils';
@@ -57,6 +58,9 @@ class PlayerControls extends LitElement {
5758
/** MediaPlayer control service instance. */
5859
private mediaControlService!: MediaControlService;
5960

61+
/** SpotifyPlus services instance. */
62+
protected spotifyPlusService!: SpotifyPlusService;
63+
6064
/** True if the card is in edit preview mode (e.g. being edited); otherwise, false. */
6165
protected isCardInEditPreview!: boolean;
6266

@@ -72,6 +76,7 @@ class PlayerControls extends LitElement {
7276
this.config = this.store.config;
7377
this.player = this.store.player;
7478
this.mediaControlService = this.store.mediaControlService;
79+
this.spotifyPlusService = this.store.spotifyPlusService;
7580

7681
const stopped = [MediaPlayerState.ON, MediaPlayerState.PLAYING, MediaPlayerState.PAUSED, MediaPlayerState.BUFFERING].includes(this.player.state) && nothing;
7782
const idle = [MediaPlayerState.IDLE].includes(this.player.state) && nothing;
@@ -465,11 +470,11 @@ class PlayerControls extends LitElement {
465470

466471
} else if (action == TURN_OFF) {
467472

468-
await this.mediaControlService.turn_off(this.player);
473+
await this.spotifyPlusService.turn_off(this.player);
469474

470475
} else if (action == TURN_ON) {
471476

472-
await this.mediaControlService.turn_on(this.player);
477+
await this.spotifyPlusService.turn_on(this.player);
473478

474479
}
475480

src/components/player-volume.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { CardConfig } from '../types/card-config';
1212
import { Store } from '../model/store';
1313
import { MediaPlayer } from '../model/media-player';
1414
import { MediaPlayerEntityFeature, MediaPlayerState } from '../services/media-control-service';
15-
import { MediaControlService } from '../services/media-control-service';
15+
import { SpotifyPlusService } from '../services/spotifyplus-service';
1616
import { ProgressEndedEvent } from '../events/progress-ended';
1717
import { ProgressStartedEvent } from '../events/progress-started';
1818
import { closestElement } from '../utils/utils';
@@ -31,8 +31,8 @@ class Volume extends LitElement {
3131
/** Card configuration data. */
3232
private config!: CardConfig;
3333

34-
/** MediaControlService services helper instance. */
35-
private mediaControlService!: MediaControlService;
34+
/** SpotifyPlus services instance. */
35+
protected spotifyPlusService!: SpotifyPlusService;
3636

3737

3838
/**
@@ -44,7 +44,7 @@ class Volume extends LitElement {
4444

4545
// set common references from application common storage area.
4646
this.config = this.store.config;
47-
this.mediaControlService = this.store.mediaControlService;
47+
this.spotifyPlusService = this.store.spotifyPlusService;
4848

4949
// get volume hide configuration setting.
5050
const hideMute = this.config.playerVolumeControlsHideMute || false;
@@ -57,7 +57,7 @@ class Volume extends LitElement {
5757

5858
// get current and max volume levels.
5959
const volume = this.player.getVolume();
60-
const maxVolume = 100; // this.getMaxVolume(volume);
60+
const maxVolume = 100;
6161

6262
// render control.
6363
return html`
@@ -103,9 +103,21 @@ class Volume extends LitElement {
103103
// show progress indicator.
104104
this.progressShow();
105105

106+
// get volume value to apply.
107+
let newVolume = Number.parseInt((args?.target as HTMLInputElement)?.value);
108+
109+
// check for max volume allowed configuration; if larger, then limit the volume value.
110+
const volumeMax: number = (this.config.playerVolumeMaxValue || 100);
111+
if (newVolume > volumeMax) {
112+
newVolume = volumeMax;
113+
const sliderControl = (args?.target as HTMLInputElement);
114+
if (sliderControl)
115+
sliderControl.value = newVolume + "";
116+
this.alertInfoSet("Selected volume level was greater than Max Volume limit set in card configuration; max limit value of " + volumeMax + " was applied.");
117+
}
118+
106119
// adjust the volume.
107-
const newVolume = Number.parseInt((args?.target as HTMLInputElement)?.value);
108-
await this.mediaControlService.volume_set(this.player, newVolume);
120+
await this.spotifyPlusService.volume_set(this.player, newVolume);
109121
return true;
110122

111123
}
@@ -137,7 +149,7 @@ class Volume extends LitElement {
137149
this.progressShow();
138150

139151
// toggle mute.
140-
await this.mediaControlService.volume_mute_toggle(this.player);
152+
await this.spotifyPlusService.volume_mute_toggle(this.player);
141153
return true;
142154

143155
}
@@ -186,11 +198,11 @@ class Volume extends LitElement {
186198
// call async service based on requested action.
187199
if (action == TURN_OFF) {
188200

189-
await this.mediaControlService.turn_off(this.player);
201+
await this.spotifyPlusService.turn_off(this.player);
190202

191203
} else if (action == TURN_ON) {
192204

193-
await this.mediaControlService.turn_on(this.player);
205+
await this.spotifyPlusService.turn_on(this.player);
194206

195207
}
196208

@@ -292,6 +304,23 @@ class Volume extends LitElement {
292304
}
293305

294306

307+
/**
308+
* Sets the alert info message in the parent player.
309+
*
310+
* @param message alert message text.
311+
*/
312+
private alertInfoSet(message: string): void {
313+
314+
// find the parent player reference, and update the message.
315+
// we have to do it this way due to the shadowDOM between this element and the player element.
316+
const spcPlayer = closestElement('#spcPlayer', this) as Player;
317+
if (spcPlayer) {
318+
spcPlayer.alertInfoSet(message);
319+
}
320+
321+
}
322+
323+
295324
/**
296325
* Returns an element style for control icon coloring.
297326
*/

src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { css } from 'lit';
22

33
/** current version of the card. */
4-
export const CARD_VERSION = '1.0.33';
4+
export const CARD_VERSION = '1.0.34';
55

66
/** SpotifyPlus integration domain identifier. */
77
export const DOMAIN_SPOTIFYPLUS = 'spotifyplus';

src/editor/device-browser-editor.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ const CONFIG_SETTINGS_SCHEMA = [
2121
required: false,
2222
type: 'string',
2323
},
24+
{
25+
name: 'deviceDefaultId',
26+
label: 'Device name / id to use for all SpotifyPlus service calls',
27+
help: 'e.g. Office Speaker',
28+
required: false,
29+
type: 'string',
30+
},
2431
{
2532
name: 'deviceBrowserItemsPerRow',
2633
label: '# of items to display per row',

src/editor/player-volume-editor.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ const CONFIG_SETTINGS_SCHEMA = [
1616
type: 'string',
1717
default: PLAYER_CONTROLS_BACKGROUND_COLOR_DEFAULT,
1818
},
19+
{
20+
name: 'playerVolumeMaxValue',
21+
label: 'Maximum volume value allowed via card UI',
22+
help: 'range 10 - 100',
23+
required: true,
24+
type: 'integer',
25+
default: 100,
26+
valueMin: 10,
27+
valueMax: 100,
28+
},
1929
{
2030
name: 'playerVolumeControlsHideMute',
2131
label: 'Hide mute button in the volume controls area',

src/model/store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class Store {
7575
this.card = card;
7676
this.hassService = new HassService(hass);
7777
this.mediaControlService = new MediaControlService(this.hassService);
78-
this.spotifyPlusService = new SpotifyPlusService(hass, card);
78+
this.spotifyPlusService = new SpotifyPlusService(hass, card, config);
7979
this.player = this.getMediaPlayerObject(playerId);
8080
this.section = section;
8181

src/services/media-control-service.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ import { MediaPlayer } from '../model/media-player';
88
import { ALERT_ERROR_SPOTIFY_PREMIUM_REQUIRED, DOMAIN_MEDIA_PLAYER } from '../constants';
99

1010
// media player services.
11-
const SERVICE_TURN_ON = "turn_on";
12-
const SERVICE_TURN_OFF = "turn_off";
11+
export const SERVICE_TURN_ON = "turn_on";
12+
export const SERVICE_TURN_OFF = "turn_off";
1313
//const SERVICE_VOLUME_UP = "volume_up";
1414
//const SERVICE_VOLUME_DOWN = "volume_down";
15-
const SERVICE_VOLUME_MUTE = "volume_mute";
16-
const SERVICE_VOLUME_SET = "volume_set";
17-
const SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause";
18-
const SERVICE_MEDIA_PLAY = "media_play";
19-
const SERVICE_MEDIA_PAUSE = "media_pause";
20-
const SERVICE_MEDIA_STOP = "media_stop";
21-
const SERVICE_MEDIA_NEXT_TRACK = "media_next_track";
22-
const SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track";
23-
const SERVICE_MEDIA_SEEK = "media_seek";
24-
const SERVICE_REPEAT_SET = "repeat_set";
25-
const SERVICE_SHUFFLE_SET = "shuffle_set";
26-
const SERVICE_CLEAR_PLAYLIST = "clear_playlist";
27-
const SERVICE_JOIN = "join";
28-
const SERVICE_PLAY_MEDIA = "play_media";
29-
const SERVICE_SELECT_SOUND_MODE = "select_sound_mode";
30-
const SERVICE_SELECT_SOURCE = "select_source";
31-
const SERVICE_UNJOIN = "unjoin";
15+
export const SERVICE_VOLUME_MUTE = "volume_mute";
16+
export const SERVICE_VOLUME_SET = "volume_set";
17+
export const SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause";
18+
export const SERVICE_MEDIA_PLAY = "media_play";
19+
export const SERVICE_MEDIA_PAUSE = "media_pause";
20+
export const SERVICE_MEDIA_STOP = "media_stop";
21+
export const SERVICE_MEDIA_NEXT_TRACK = "media_next_track";
22+
export const SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track";
23+
export const SERVICE_MEDIA_SEEK = "media_seek";
24+
export const SERVICE_REPEAT_SET = "repeat_set";
25+
export const SERVICE_SHUFFLE_SET = "shuffle_set";
26+
export const SERVICE_CLEAR_PLAYLIST = "clear_playlist";
27+
export const SERVICE_JOIN = "join";
28+
export const SERVICE_PLAY_MEDIA = "play_media";
29+
export const SERVICE_SELECT_SOUND_MODE = "select_sound_mode";
30+
export const SERVICE_SELECT_SOURCE = "select_source";
31+
export const SERVICE_UNJOIN = "unjoin";
3232

3333

3434
export class MediaControlService {
@@ -452,7 +452,6 @@ export class MediaControlService {
452452
* if unmuted, then it will be muted;
453453
*
454454
* @param player MediaPlayer object to control.
455-
* @param muteVolume True to mute the volume; otherwise, False to unmute the volume.
456455
*/
457456
public async volume_mute_toggle(player: MediaPlayer) {
458457

0 commit comments

Comments
 (0)