diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py
index b69400142e0f843329876ba33174543a22cedeb5..e1d489125a3440dd621ff5376ddfd7a3364c6c1f 100644
--- a/homeassistant/components/frontend/version.py
+++ b/homeassistant/components/frontend/version.py
@@ -1,2 +1,2 @@
 """ DO NOT MODIFY. Auto-generated by build_frontend script """
-VERSION = "6fb0e76d325bb7472fa25355e60539cd"
+VERSION = "3c6a5149feced6c49cb97b76fdf14fee"
diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html
index 1a23b7069882fe08b229e2e8ec2e022b85c7e601..c8837e05d6a93ed712794f64154ad17f16885333 100644
--- a/homeassistant/components/frontend/www_static/frontend.html
+++ b/homeassistant/components/frontend/www_static/frontend.html
@@ -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);
     },
   });
diff --git a/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-light.html b/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-light.html
index 32c31948875be0409cc532939d13fec8df834c79..b9d49e1f4747faa62ce96c3ac335172afd2f2c3d 100644
--- a/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-light.html
+++ b/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-light.html
@@ -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 {
diff --git a/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-media_player.html b/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-media_player.html
index 8dd20fdbabe485e8dc5a4c4093cc3747f2048aed..408e863d647c21a379237df76e445b65d0142aba 100644
--- a/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-media_player.html
+++ b/homeassistant/components/frontend/www_static/polymer/more-infos/more-info-media_player.html
@@ -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);
     },
   });
diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py
index 0ce00eae43f5b2c675ec84841e8afcc3bbd52891..2b555faa5030f46366f66b657b4941f46d2c0164 100644
--- a/homeassistant/components/media_player/__init__.py
+++ b/homeassistant/components/media_player/__init__.py
@@ -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
diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py
index 33ac14efa1e96da5c96ea7f7b3fb159f2e4deaa6..0ed5b2bc5b62161cd3b5ce87812abd0950ce37d1 100644
--- a/homeassistant/components/media_player/cast.py
+++ b/homeassistant/components/media_player/cast.py
@@ -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
diff --git a/homeassistant/const.py b/homeassistant/const.py
index cfd37576ff1e9b1ccd1af553aef13de7227c6e6b..a4ea2651d289d49e721186722f245e97729db410 100644
--- a/homeassistant/const.py
+++ b/homeassistant/const.py
@@ -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"