Merge pull request #152 from wind-rider/dev
Initial commit for volume slider in media player more info cardpull/150/merge
commit
9efc357226
|
@ -1,2 +1,2 @@
|
|||
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
||||
VERSION = "6fb0e76d325bb7472fa25355e60539cd"
|
||||
VERSION = "3c6a5149feced6c49cb97b76fdf14fee"
|
||||
|
|
|
@ -25617,11 +25617,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
transition: max-height .5s ease-in;
|
||||
}
|
||||
|
||||
.brightness paper-slider::shadow #sliderKnobInner,
|
||||
.brightness paper-slider::shadow #sliderBar::shadow #activeProgress {
|
||||
background-color: #039be5;
|
||||
}
|
||||
|
||||
color-picker {
|
||||
display: block;
|
||||
width: 350px;
|
||||
|
@ -25633,7 +25628,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
}
|
||||
|
||||
.has-brightness .brightness {
|
||||
max-height: 500px;
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.has-xy_color color-picker {
|
||||
|
@ -25722,21 +25717,40 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
paper-button, paper-icon-button {
|
||||
paper-icon-button {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.volume {
|
||||
margin-bottom: 8px;
|
||||
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .5s ease-in;
|
||||
}
|
||||
|
||||
.has-media_volume .volume {
|
||||
max-height: 40px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="layout horizontal">
|
||||
<div class="flex">
|
||||
<paper-icon-button icon="power-settings-new" on-tap="handleTogglePower"></paper-icon-button>
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="layout horizontal">
|
||||
<div class="flex">
|
||||
<paper-icon-button icon="power-settings-new" on-tap="handleTogglePower"></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<template is="dom-if" if="[[!isIdle]]">
|
||||
<paper-icon-button icon="av:skip-previous" on-tap="handlePrevious"></paper-icon-button>
|
||||
<paper-icon-button icon="[[computePlayPauseIcon(stateObj)]]" on-tap="handlePlayPause"></paper-icon-button>
|
||||
<paper-icon-button icon="av:skip-next" on-tap="handleNext"></paper-icon-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<template is="dom-if" if="[[!isIdle]]">
|
||||
<paper-icon-button icon="av:skip-previous" on-tap="handlePrevious"></paper-icon-button>
|
||||
<paper-icon-button icon="[[computePlayPauseIcon(stateObj)]]" on-tap="handlePlayPause"></paper-icon-button>
|
||||
<paper-icon-button icon="av:skip-next" on-tap="handleNext"></paper-icon-button>
|
||||
</template>
|
||||
<div class="volume center horizontal layout">
|
||||
<div>Volume</div>
|
||||
<paper-slider min="0" max="100" value="{{volumeSliderValue}}" on-change="volumeSliderChanged" class="flex">
|
||||
</paper-slider>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -25745,6 +25759,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
<script>
|
||||
(function() {
|
||||
var serviceActions = window.hass.serviceActions;
|
||||
var uiUtil = window.hass.uiUtil;
|
||||
var ATTRIBUTE_CLASSES = ['media_volume'];
|
||||
|
||||
Polymer({
|
||||
is: 'more-info-media_player',
|
||||
|
@ -25752,12 +25768,32 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
properties: {
|
||||
stateObj: {
|
||||
type: Object,
|
||||
observer: 'stateObjChanged',
|
||||
},
|
||||
|
||||
isIdle: {
|
||||
type: Boolean,
|
||||
computed: 'computeIsIdle(stateObj)',
|
||||
},
|
||||
|
||||
volumeSliderValue: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
}
|
||||
},
|
||||
|
||||
stateObjChanged: function(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.volumeSliderValue = newVal.attributes.media_volume * 100;
|
||||
}
|
||||
|
||||
this.debounce('more-info-volume-animation-finish', function() {
|
||||
this.fire('iron-resize');
|
||||
}.bind(this), 500);
|
||||
},
|
||||
|
||||
computeClassNames: function(stateObj) {
|
||||
return uiUtil.attributeClassNames(stateObj, ATTRIBUTE_CLASSES);
|
||||
},
|
||||
|
||||
computeMediaState: function(stateObj) {
|
||||
|
@ -25792,8 +25828,16 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
this.callService('media_next_track');
|
||||
},
|
||||
|
||||
callService: function(service) {
|
||||
var data = {entity_id: this.stateObj.entityId};
|
||||
volumeSliderChanged: function(ev) {
|
||||
var volPercentage = parseFloat(ev.target.value);
|
||||
var vol = volPercentage > 0 ? volPercentage / 100 : 0;
|
||||
|
||||
this.callService('volume_set', {volume: vol});
|
||||
},
|
||||
|
||||
callService: function(service, data) {
|
||||
data = data || {};
|
||||
data.entity_id = this.stateObj.entityId;
|
||||
serviceActions.callService('media_player', service, data);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,11 +13,6 @@
|
|||
transition: max-height .5s ease-in;
|
||||
}
|
||||
|
||||
.brightness paper-slider::shadow #sliderKnobInner,
|
||||
.brightness paper-slider::shadow #sliderBar::shadow #activeProgress {
|
||||
background-color: #039be5;
|
||||
}
|
||||
|
||||
color-picker {
|
||||
display: block;
|
||||
width: 350px;
|
||||
|
@ -29,7 +24,7 @@
|
|||
}
|
||||
|
||||
.has-brightness .brightness {
|
||||
max-height: 500px;
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.has-xy_color color-picker {
|
||||
|
|
|
@ -8,25 +8,46 @@
|
|||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
paper-button, paper-icon-button {
|
||||
paper-icon-button {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.volume {
|
||||
margin-bottom: 8px;
|
||||
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .5s ease-in;
|
||||
}
|
||||
|
||||
.has-media_volume .volume {
|
||||
max-height: 40px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class='layout horizontal'>
|
||||
<div class='flex'>
|
||||
<paper-icon-button icon='power-settings-new'
|
||||
on-tap='handleTogglePower'></paper-icon-button>
|
||||
<div class$='[[computeClassNames(stateObj)]]'>
|
||||
<div class='layout horizontal'>
|
||||
<div class='flex'>
|
||||
<paper-icon-button icon='power-settings-new'
|
||||
on-tap='handleTogglePower'></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<template is='dom-if' if='[[!isIdle]]'>
|
||||
<paper-icon-button icon='av:skip-previous'
|
||||
on-tap='handlePrevious'></paper-icon-button>
|
||||
<paper-icon-button icon='[[computePlayPauseIcon(stateObj)]]'
|
||||
on-tap='handlePlayPause'></paper-icon-button>
|
||||
<paper-icon-button icon='av:skip-next'
|
||||
on-tap='handleNext'></paper-icon-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<template is='dom-if' if='[[!isIdle]]'>
|
||||
<paper-icon-button icon='av:skip-previous'
|
||||
on-tap='handlePrevious'></paper-icon-button>
|
||||
<paper-icon-button icon='[[computePlayPauseIcon(stateObj)]]'
|
||||
on-tap='handlePlayPause'></paper-icon-button>
|
||||
<paper-icon-button icon='av:skip-next'
|
||||
on-tap='handleNext'></paper-icon-button>
|
||||
</template>
|
||||
<div class='volume center horizontal layout'>
|
||||
<div>Volume</div>
|
||||
<paper-slider
|
||||
min='0' max='100' value='{{volumeSliderValue}}'
|
||||
on-change='volumeSliderChanged' class='flex'>
|
||||
</paper-slider>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -35,6 +56,8 @@
|
|||
<script>
|
||||
(function() {
|
||||
var serviceActions = window.hass.serviceActions;
|
||||
var uiUtil = window.hass.uiUtil;
|
||||
var ATTRIBUTE_CLASSES = ['media_volume'];
|
||||
|
||||
Polymer({
|
||||
is: 'more-info-media_player',
|
||||
|
@ -42,12 +65,32 @@
|
|||
properties: {
|
||||
stateObj: {
|
||||
type: Object,
|
||||
observer: 'stateObjChanged',
|
||||
},
|
||||
|
||||
isIdle: {
|
||||
type: Boolean,
|
||||
computed: 'computeIsIdle(stateObj)',
|
||||
},
|
||||
|
||||
volumeSliderValue: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
}
|
||||
},
|
||||
|
||||
stateObjChanged: function(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.volumeSliderValue = newVal.attributes.media_volume * 100;
|
||||
}
|
||||
|
||||
this.debounce('more-info-volume-animation-finish', function() {
|
||||
this.fire('iron-resize');
|
||||
}.bind(this), 500);
|
||||
},
|
||||
|
||||
computeClassNames: function(stateObj) {
|
||||
return uiUtil.attributeClassNames(stateObj, ATTRIBUTE_CLASSES);
|
||||
},
|
||||
|
||||
computeMediaState: function(stateObj) {
|
||||
|
@ -82,8 +125,16 @@
|
|||
this.callService('media_next_track');
|
||||
},
|
||||
|
||||
callService: function(service) {
|
||||
var data = {entity_id: this.stateObj.entityId};
|
||||
volumeSliderChanged: function(ev) {
|
||||
var volPercentage = parseFloat(ev.target.value);
|
||||
var vol = volPercentage > 0 ? volPercentage / 100 : 0;
|
||||
|
||||
this.callService('volume_set', {volume: vol});
|
||||
},
|
||||
|
||||
callService: function(service, data) {
|
||||
data = data || {};
|
||||
data.entity_id = this.stateObj.entityId;
|
||||
serviceActions.callService('media_player', service, data);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,9 +10,11 @@ from homeassistant.components import discovery
|
|||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_UP,
|
||||
SERVICE_VOLUME_DOWN, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_PLAY,
|
||||
SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PREV_TRACK)
|
||||
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
||||
SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PAUSE,
|
||||
SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PREV_TRACK)
|
||||
|
||||
DOMAIN = 'media_player'
|
||||
DEPENDENCIES = []
|
||||
|
@ -86,6 +88,25 @@ def volume_down(hass, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_VOLUME_DOWN, data)
|
||||
|
||||
|
||||
def volume_mute(hass, entity_id=None):
|
||||
""" Send the media player the command for volume down. """
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
|
||||
hass.services.call(DOMAIN, SERVICE_VOLUME_MUTE, data)
|
||||
|
||||
|
||||
def volume_set(hass, entity_id=None, volume=None):
|
||||
""" Send the media player the command for volume down. """
|
||||
data = {
|
||||
key: value for key, value in [
|
||||
(ATTR_ENTITY_ID, entity_id),
|
||||
(ATTR_MEDIA_VOLUME, volume),
|
||||
] if value is not None
|
||||
}
|
||||
|
||||
hass.services.call(DOMAIN, SERVICE_VOLUME_SET, data)
|
||||
|
||||
|
||||
def media_play_pause(hass, entity_id=None):
|
||||
""" Send the media player the command for play/pause. """
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
|
@ -126,6 +147,7 @@ SERVICE_TO_METHOD = {
|
|||
SERVICE_TURN_OFF: 'turn_off',
|
||||
SERVICE_VOLUME_UP: 'volume_up',
|
||||
SERVICE_VOLUME_DOWN: 'volume_down',
|
||||
SERVICE_VOLUME_MUTE: 'volume_mute',
|
||||
SERVICE_MEDIA_PLAY_PAUSE: 'media_play_pause',
|
||||
SERVICE_MEDIA_PLAY: 'media_play',
|
||||
SERVICE_MEDIA_PAUSE: 'media_pause',
|
||||
|
@ -157,6 +179,19 @@ def setup(hass, config):
|
|||
for service in SERVICE_TO_METHOD:
|
||||
hass.services.register(DOMAIN, service, media_player_service_handler)
|
||||
|
||||
def volume_set_service(service, volume):
|
||||
""" Set specified volume on the media player. """
|
||||
target_players = component.extract_from_service(service)
|
||||
|
||||
if volume:
|
||||
for player in target_players:
|
||||
player.volume_set(volume)
|
||||
|
||||
hass.services.register(DOMAIN, SERVICE_VOLUME_SET,
|
||||
lambda service:
|
||||
volume_set_service(
|
||||
service, service.data.get('volume')))
|
||||
|
||||
def play_youtube_video_service(service, media_id):
|
||||
""" Plays specified media_id on the media player. """
|
||||
target_players = component.extract_from_service(service)
|
||||
|
@ -200,6 +235,14 @@ class MediaPlayerDevice(Entity):
|
|||
""" volume_down media player. """
|
||||
pass
|
||||
|
||||
def volume_mute(self):
|
||||
""" mute media player. """
|
||||
pass
|
||||
|
||||
def volume_set(self, volume):
|
||||
""" set volume level of media player. """
|
||||
pass
|
||||
|
||||
def media_play_pause(self):
|
||||
""" media_play_pause media player. """
|
||||
pass
|
||||
|
|
|
@ -116,7 +116,7 @@ class CastDevice(MediaPlayerDevice):
|
|||
}
|
||||
|
||||
if cast_status:
|
||||
state_attr[ATTR_MEDIA_VOLUME] = cast_status.volume_level,
|
||||
state_attr[ATTR_MEDIA_VOLUME] = cast_status.volume_level
|
||||
|
||||
if media_status.content_id:
|
||||
state_attr[ATTR_MEDIA_CONTENT_ID] = media_status.content_id
|
||||
|
@ -156,6 +156,14 @@ class CastDevice(MediaPlayerDevice):
|
|||
""" Service to send the chromecast the command for volume down. """
|
||||
self.cast.volume_down()
|
||||
|
||||
def volume_mute(self):
|
||||
""" Service to send the chromecast the command for volume up. """
|
||||
self.cast.set_volume(0)
|
||||
|
||||
def volume_set(self, volume):
|
||||
""" Service to send the chromecast the command for volume down. """
|
||||
self.cast.set_volume(volume)
|
||||
|
||||
def media_play_pause(self):
|
||||
""" Service to send the chromecast the command for play/pause. """
|
||||
media_state = self.media_state
|
||||
|
|
|
@ -99,6 +99,7 @@ SERVICE_TURN_OFF = 'turn_off'
|
|||
SERVICE_VOLUME_UP = "volume_up"
|
||||
SERVICE_VOLUME_DOWN = "volume_down"
|
||||
SERVICE_VOLUME_MUTE = "volume_mute"
|
||||
SERVICE_VOLUME_SET = "volume_set"
|
||||
SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause"
|
||||
SERVICE_MEDIA_PLAY = "media_play"
|
||||
SERVICE_MEDIA_PAUSE = "media_pause"
|
||||
|
|
Loading…
Reference in New Issue