Merge pull request #152 from wind-rider/dev

Initial commit for volume slider in media player more info card
pull/150/merge
Paulus Schoutsen 2015-05-31 11:47:11 -07:00
commit 9efc357226
7 changed files with 187 additions and 45 deletions

View File

@ -1,2 +1,2 @@
""" DO NOT MODIFY. Auto-generated by build_frontend script """
VERSION = "6fb0e76d325bb7472fa25355e60539cd"
VERSION = "3c6a5149feced6c49cb97b76fdf14fee"

View File

@ -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);
},
});

View File

@ -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 {

View File

@ -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);
},
});

View File

@ -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

View File

@ -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

View File

@ -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"