Skip to content

Commit

Permalink
[ 1.0.34 ] * Added card configuration option deviceDefaultId for sp…
Browse files Browse the repository at this point in the history
…ecifying 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.
  • Loading branch information
thlucas1 committed Jan 27, 2025
1 parent ea4ea56 commit cdb7667
Show file tree
Hide file tree
Showing 10 changed files with 453 additions and 37 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ Change are listed in reverse chronological order (newest to oldest).

<span class="changelog">

###### [ 1.0.34 ] - 2025/01/26

* 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.0.33 ] - 2025/01/23

* 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.
Expand Down
9 changes: 7 additions & 2 deletions src/components/player-controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { Store } from '../model/store';
import { MediaPlayer } from '../model/media-player';
import { MediaPlayerEntityFeature, MediaPlayerState, RepeatMode } from '../services/media-control-service';
import { MediaControlService } from '../services/media-control-service';
import { SpotifyPlusService } from '../services/spotifyplus-service';
import { ProgressEndedEvent } from '../events/progress-ended';
import { ProgressStartedEvent } from '../events/progress-started';
import { closestElement, isCardInEditPreview } from '../utils/utils';
Expand Down Expand Up @@ -57,6 +58,9 @@ class PlayerControls extends LitElement {
/** MediaPlayer control service instance. */
private mediaControlService!: MediaControlService;

/** SpotifyPlus services instance. */
protected spotifyPlusService!: SpotifyPlusService;

/** True if the card is in edit preview mode (e.g. being edited); otherwise, false. */
protected isCardInEditPreview!: boolean;

Expand All @@ -72,6 +76,7 @@ class PlayerControls extends LitElement {
this.config = this.store.config;
this.player = this.store.player;
this.mediaControlService = this.store.mediaControlService;
this.spotifyPlusService = this.store.spotifyPlusService;

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

} else if (action == TURN_OFF) {

await this.mediaControlService.turn_off(this.player);
await this.spotifyPlusService.turn_off(this.player);

} else if (action == TURN_ON) {

await this.mediaControlService.turn_on(this.player);
await this.spotifyPlusService.turn_on(this.player);

}

Expand Down
49 changes: 39 additions & 10 deletions src/components/player-volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CardConfig } from '../types/card-config';
import { Store } from '../model/store';
import { MediaPlayer } from '../model/media-player';
import { MediaPlayerEntityFeature, MediaPlayerState } from '../services/media-control-service';
import { MediaControlService } from '../services/media-control-service';
import { SpotifyPlusService } from '../services/spotifyplus-service';
import { ProgressEndedEvent } from '../events/progress-ended';
import { ProgressStartedEvent } from '../events/progress-started';
import { closestElement } from '../utils/utils';
Expand All @@ -31,8 +31,8 @@ class Volume extends LitElement {
/** Card configuration data. */
private config!: CardConfig;

/** MediaControlService services helper instance. */
private mediaControlService!: MediaControlService;
/** SpotifyPlus services instance. */
protected spotifyPlusService!: SpotifyPlusService;


/**
Expand All @@ -44,7 +44,7 @@ class Volume extends LitElement {

// set common references from application common storage area.
this.config = this.store.config;
this.mediaControlService = this.store.mediaControlService;
this.spotifyPlusService = this.store.spotifyPlusService;

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

// get current and max volume levels.
const volume = this.player.getVolume();
const maxVolume = 100; // this.getMaxVolume(volume);
const maxVolume = 100;

// render control.
return html`
Expand Down Expand Up @@ -103,9 +103,21 @@ class Volume extends LitElement {
// show progress indicator.
this.progressShow();

// get volume value to apply.
let newVolume = Number.parseInt((args?.target as HTMLInputElement)?.value);

// check for max volume allowed configuration; if larger, then limit the volume value.
const volumeMax: number = (this.config.playerVolumeMaxValue || 100);
if (newVolume > volumeMax) {
newVolume = volumeMax;
const sliderControl = (args?.target as HTMLInputElement);
if (sliderControl)
sliderControl.value = newVolume + "";
this.alertInfoSet("Selected volume level was greater than Max Volume limit set in card configuration; max limit value of " + volumeMax + " was applied.");
}

// adjust the volume.
const newVolume = Number.parseInt((args?.target as HTMLInputElement)?.value);
await this.mediaControlService.volume_set(this.player, newVolume);
await this.spotifyPlusService.volume_set(this.player, newVolume);
return true;

}
Expand Down Expand Up @@ -137,7 +149,7 @@ class Volume extends LitElement {
this.progressShow();

// toggle mute.
await this.mediaControlService.volume_mute_toggle(this.player);
await this.spotifyPlusService.volume_mute_toggle(this.player);
return true;

}
Expand Down Expand Up @@ -186,11 +198,11 @@ class Volume extends LitElement {
// call async service based on requested action.
if (action == TURN_OFF) {

await this.mediaControlService.turn_off(this.player);
await this.spotifyPlusService.turn_off(this.player);

} else if (action == TURN_ON) {

await this.mediaControlService.turn_on(this.player);
await this.spotifyPlusService.turn_on(this.player);

}

Expand Down Expand Up @@ -292,6 +304,23 @@ class Volume extends LitElement {
}


/**
* Sets the alert info message in the parent player.
*
* @param message alert message text.
*/
private alertInfoSet(message: string): void {

// find the parent player reference, and update the message.
// we have to do it this way due to the shadowDOM between this element and the player element.
const spcPlayer = closestElement('#spcPlayer', this) as Player;
if (spcPlayer) {
spcPlayer.alertInfoSet(message);
}

}


/**
* Returns an element style for control icon coloring.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from 'lit';

/** current version of the card. */
export const CARD_VERSION = '1.0.33';
export const CARD_VERSION = '1.0.34';

/** SpotifyPlus integration domain identifier. */
export const DOMAIN_SPOTIFYPLUS = 'spotifyplus';
Expand Down
7 changes: 7 additions & 0 deletions src/editor/device-browser-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ const CONFIG_SETTINGS_SCHEMA = [
required: false,
type: 'string',
},
{
name: 'deviceDefaultId',
label: 'Device name / id to use for all SpotifyPlus service calls',
help: 'e.g. Office Speaker',
required: false,
type: 'string',
},
{
name: 'deviceBrowserItemsPerRow',
label: '# of items to display per row',
Expand Down
10 changes: 10 additions & 0 deletions src/editor/player-volume-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ const CONFIG_SETTINGS_SCHEMA = [
type: 'string',
default: PLAYER_CONTROLS_BACKGROUND_COLOR_DEFAULT,
},
{
name: 'playerVolumeMaxValue',
label: 'Maximum volume value allowed via card UI',
help: 'range 10 - 100',
required: true,
type: 'integer',
default: 100,
valueMin: 10,
valueMax: 100,
},
{
name: 'playerVolumeControlsHideMute',
label: 'Hide mute button in the volume controls area',
Expand Down
2 changes: 1 addition & 1 deletion src/model/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class Store {
this.card = card;
this.hassService = new HassService(hass);
this.mediaControlService = new MediaControlService(this.hassService);
this.spotifyPlusService = new SpotifyPlusService(hass, card);
this.spotifyPlusService = new SpotifyPlusService(hass, card, config);
this.player = this.getMediaPlayerObject(playerId);
this.section = section;

Expand Down
39 changes: 19 additions & 20 deletions src/services/media-control-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ import { MediaPlayer } from '../model/media-player';
import { ALERT_ERROR_SPOTIFY_PREMIUM_REQUIRED, DOMAIN_MEDIA_PLAYER } from '../constants';

// media player services.
const SERVICE_TURN_ON = "turn_on";
const SERVICE_TURN_OFF = "turn_off";
export const SERVICE_TURN_ON = "turn_on";
export const SERVICE_TURN_OFF = "turn_off";
//const SERVICE_VOLUME_UP = "volume_up";
//const SERVICE_VOLUME_DOWN = "volume_down";
const SERVICE_VOLUME_MUTE = "volume_mute";
const SERVICE_VOLUME_SET = "volume_set";
const SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause";
const SERVICE_MEDIA_PLAY = "media_play";
const SERVICE_MEDIA_PAUSE = "media_pause";
const SERVICE_MEDIA_STOP = "media_stop";
const SERVICE_MEDIA_NEXT_TRACK = "media_next_track";
const SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track";
const SERVICE_MEDIA_SEEK = "media_seek";
const SERVICE_REPEAT_SET = "repeat_set";
const SERVICE_SHUFFLE_SET = "shuffle_set";
const SERVICE_CLEAR_PLAYLIST = "clear_playlist";
const SERVICE_JOIN = "join";
const SERVICE_PLAY_MEDIA = "play_media";
const SERVICE_SELECT_SOUND_MODE = "select_sound_mode";
const SERVICE_SELECT_SOURCE = "select_source";
const SERVICE_UNJOIN = "unjoin";
export const SERVICE_VOLUME_MUTE = "volume_mute";
export const SERVICE_VOLUME_SET = "volume_set";
export const SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause";
export const SERVICE_MEDIA_PLAY = "media_play";
export const SERVICE_MEDIA_PAUSE = "media_pause";
export const SERVICE_MEDIA_STOP = "media_stop";
export const SERVICE_MEDIA_NEXT_TRACK = "media_next_track";
export const SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track";
export const SERVICE_MEDIA_SEEK = "media_seek";
export const SERVICE_REPEAT_SET = "repeat_set";
export const SERVICE_SHUFFLE_SET = "shuffle_set";
export const SERVICE_CLEAR_PLAYLIST = "clear_playlist";
export const SERVICE_JOIN = "join";
export const SERVICE_PLAY_MEDIA = "play_media";
export const SERVICE_SELECT_SOUND_MODE = "select_sound_mode";
export const SERVICE_SELECT_SOURCE = "select_source";
export const SERVICE_UNJOIN = "unjoin";


export class MediaControlService {
Expand Down Expand Up @@ -452,7 +452,6 @@ export class MediaControlService {
* if unmuted, then it will be muted;
*
* @param player MediaPlayer object to control.
* @param muteVolume True to mute the volume; otherwise, False to unmute the volume.
*/
public async volume_mute_toggle(player: MediaPlayer) {

Expand Down
Loading

0 comments on commit cdb7667

Please sign in to comment.