20260326
This commit is contained in:
560
esphome/widgets/media_player/media_player.yaml
Normal file
560
esphome/widgets/media_player/media_player.yaml
Normal file
@@ -0,0 +1,560 @@
|
||||
substitutions:
|
||||
ha_server: "http://192.168.1.44:8123"
|
||||
media_player_entity: "media_player.yandex_station_m00bv9j00dc7sg"
|
||||
|
||||
power_icon: "\U0000e909"
|
||||
play_icon: "\U0000e90a"
|
||||
pause_icon: "\U0000e90b"
|
||||
back_step_icon: "\U0000e90c"
|
||||
forward_step_icon: "\U0000e90d"
|
||||
volume_off_icon: "\U0000e90e"
|
||||
volume_on_icon: "\U0000e90f"
|
||||
volume_minus_icon: "\U0000e910"
|
||||
volume_plus_icon: "\U0000e911"
|
||||
repeat_all_icon: "\U0000e912"
|
||||
repeat_off_icon: "\U0000e913"
|
||||
repeat_one_icon: "\U0000e914"
|
||||
|
||||
globals:
|
||||
- id: repeat_modes
|
||||
type: std::vector<std::string>
|
||||
initial_value: '{"all", "one", "off"}'
|
||||
- id: repeat_icons
|
||||
type: std::vector<std::string>
|
||||
initial_value: '{"${repeat_all_icon}", "${repeat_one_icon}", "${repeat_off_icon}"}'
|
||||
- id: current_repeat_mode_idx
|
||||
type: int
|
||||
initial_value: '0'
|
||||
- id: tmp_repeat_mode
|
||||
type: std::string
|
||||
restore_value: no
|
||||
initial_value: '"all"'
|
||||
- id: tmp_repeat_icon
|
||||
type: std::string
|
||||
restore_value: no
|
||||
initial_value: '"${repeat_all_icon}"'
|
||||
- id: cover_url
|
||||
type: std::string
|
||||
restore_value: no
|
||||
initial_value: '""'
|
||||
- id: duration_slider_user_interaction
|
||||
type: bool
|
||||
restore_value: no
|
||||
initial_value: 'false'
|
||||
- id: slider_position
|
||||
type: float
|
||||
restore_value: no
|
||||
initial_value: '0.0'
|
||||
- id: pending_cover_url
|
||||
type: std::string
|
||||
restore_value: no
|
||||
initial_value: '""'
|
||||
- id: pending_repeat_value
|
||||
type: std::string
|
||||
restore_value: no
|
||||
initial_value: '""'
|
||||
|
||||
script:
|
||||
- id: update_cover_script
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string url = id(pending_cover_url);
|
||||
id(cover_url) = url;
|
||||
- homeassistant.action:
|
||||
action: display_tools.save_media_cover
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
size: small
|
||||
- delay: 1s
|
||||
- online_image.release: media_image_jpeg
|
||||
- online_image.set_url:
|
||||
id: media_image_jpeg
|
||||
url: "${ha_server}/local/display_tools/cover.jpeg"
|
||||
|
||||
- id: update_repeat_mode_script
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string x = id(pending_repeat_value);
|
||||
auto modes = id(repeat_modes);
|
||||
auto icons = id(repeat_icons);
|
||||
for (int i = 0; i < modes.size(); i++) {
|
||||
if (modes[i] == x) {
|
||||
id(current_repeat_mode_idx) = i;
|
||||
id(tmp_repeat_mode) = modes[i];
|
||||
id(tmp_repeat_icon) = icons[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
- lvgl.label.update:
|
||||
id: media_player_repeat_label
|
||||
text: !lambda 'return id(tmp_repeat_icon);'
|
||||
|
||||
- id: handle_repeat_press_script
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: |-
|
||||
int idx = id(current_repeat_mode_idx);
|
||||
auto modes = id(repeat_modes);
|
||||
auto icons = id(repeat_icons);
|
||||
idx = (idx + 1) % modes.size();
|
||||
id(current_repeat_mode_idx) = idx;
|
||||
std::string new_mode = modes[idx];
|
||||
std::string new_icon = icons[idx];
|
||||
id(tmp_repeat_mode) = new_mode;
|
||||
id(tmp_repeat_icon) = new_icon;
|
||||
- lvgl.label.update:
|
||||
id: media_player_repeat_label
|
||||
text: !lambda 'return id(tmp_repeat_icon);'
|
||||
- homeassistant.action:
|
||||
action: media_player.repeat_set
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
repeat: !lambda 'return id(tmp_repeat_mode);'
|
||||
|
||||
- id: handle_duration_slider_release_script
|
||||
mode: restart
|
||||
then:
|
||||
- homeassistant.service:
|
||||
service: media_player.media_seek
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
seek_position: !lambda 'return std::to_string(int(id(slider_position)));'
|
||||
- delay: 2s
|
||||
- lambda: |-
|
||||
id(duration_slider_user_interaction) = false;
|
||||
|
||||
lvgl:
|
||||
pages:
|
||||
- id: media_player_page
|
||||
bg_color: color_slate_blue_gray
|
||||
widgets:
|
||||
|
||||
# Cover
|
||||
- obj:
|
||||
id: media_cover
|
||||
x: 10
|
||||
y: 10
|
||||
width: 140
|
||||
height: 140
|
||||
align: TOP_LEFT
|
||||
bg_color: color_steel_blue
|
||||
bg_image_src: media_image_jpeg
|
||||
border_color: color_slate_blue_gray
|
||||
border_width: 10
|
||||
shadow_opa: TRANSP
|
||||
radius: 20
|
||||
|
||||
# Title/Artist/Duration
|
||||
- obj:
|
||||
x: -20
|
||||
y: 20
|
||||
width: 300
|
||||
height: 120
|
||||
align: TOP_RIGHT
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 20%
|
||||
border_opa: TRANSP
|
||||
border_width: 0
|
||||
shadow_opa: TRANSP
|
||||
radius: 10
|
||||
widgets:
|
||||
- label:
|
||||
id: media_player_title_label
|
||||
height: 40
|
||||
width: 260
|
||||
long_mode: DOT
|
||||
y: -25
|
||||
align: CENTER
|
||||
text_color: color_misty_blue
|
||||
text_font: nunito_20
|
||||
text: "Title"
|
||||
- label:
|
||||
id: media_player_artist_label
|
||||
height: 30
|
||||
width: 260
|
||||
long_mode: DOT
|
||||
y: 3
|
||||
align: CENTER
|
||||
text_color: color_misty_blue
|
||||
text_font: nunito_16
|
||||
text: "Artist"
|
||||
- slider:
|
||||
id: media_player_duration_pos_slider
|
||||
radius: 2
|
||||
y: 35
|
||||
bg_color: color_slate_blue_gray
|
||||
align: CENTER
|
||||
width: 260
|
||||
height: 5
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
indicator:
|
||||
bg_color: color_misty_blue
|
||||
radius: 2
|
||||
knob:
|
||||
bg_opa: TRANSP
|
||||
on_press:
|
||||
- lambda: |-
|
||||
id(duration_slider_user_interaction) = true;
|
||||
on_release:
|
||||
- lambda: |-
|
||||
id(slider_position) = x;
|
||||
- script.execute: handle_duration_slider_release_script
|
||||
|
||||
# Controls
|
||||
- obj:
|
||||
y: 160
|
||||
width: 440
|
||||
height: 120
|
||||
align: TOP_MID
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 20%
|
||||
border_opa: TRANSP
|
||||
shadow_opa: TRANSP
|
||||
radius: 10
|
||||
widgets:
|
||||
# Off
|
||||
- label:
|
||||
x: 10
|
||||
align: LEFT_MID
|
||||
text_color: color_steel_blue
|
||||
text_font: icons_38
|
||||
text: "${power_icon}"
|
||||
on_press:
|
||||
- homeassistant.action:
|
||||
action: media_player.turn_off
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
# back
|
||||
- label:
|
||||
x: -80
|
||||
align: CENTER
|
||||
text_color: color_misty_blue
|
||||
text_font: icons_38
|
||||
text: "${back_step_icon}"
|
||||
on_press:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_previous_track
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
|
||||
# play / pause
|
||||
- obj:
|
||||
id: media_player_control_play_bg
|
||||
height: 90
|
||||
width: 90
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 80%
|
||||
border_opa: TRANSP
|
||||
radius: 50
|
||||
align: CENTER
|
||||
widgets:
|
||||
- label:
|
||||
id: media_player_state_label
|
||||
align: CENTER
|
||||
text_color: color_misty_blue
|
||||
text_font: icons_48
|
||||
text: "${play_icon}"
|
||||
on_press:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(media_player_state).state == "playing";'
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_pause
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
else:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_play
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
|
||||
# forward
|
||||
- label:
|
||||
x: 80
|
||||
align: CENTER
|
||||
text_color: color_misty_blue
|
||||
text_font: icons_38
|
||||
text: "${forward_step_icon}"
|
||||
on_press:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_next_track
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
|
||||
# repeat
|
||||
- label:
|
||||
id: media_player_repeat_label
|
||||
x: -10
|
||||
align: RIGHT_MID
|
||||
text_color: color_steel_blue
|
||||
text_font: icons_38
|
||||
text: "${repeat_all_icon}"
|
||||
on_press:
|
||||
- script.execute: handle_repeat_press_script
|
||||
|
||||
# Volume
|
||||
- obj:
|
||||
y: 300
|
||||
width: 440
|
||||
height: 80
|
||||
align: TOP_MID
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 20%
|
||||
border_opa: TRANSP
|
||||
shadow_opa: TRANSP
|
||||
radius: 10
|
||||
widgets:
|
||||
# mute
|
||||
- label:
|
||||
id: media_player_mute_label
|
||||
x: 10
|
||||
align: LEFT_MID
|
||||
text_color: color_steel_blue
|
||||
text_font: icons_32
|
||||
text: "${volume_on_icon}"
|
||||
on_press:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(media_player_is_volume_muted).state;'
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_mute
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
is_volume_muted: "false"
|
||||
else:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_mute
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
is_volume_muted: "true"
|
||||
|
||||
# vol down
|
||||
- label:
|
||||
id: media_player_vol_down_label
|
||||
x: -280
|
||||
align: RIGHT_MID
|
||||
text_color: color_steel_blue
|
||||
text_font: icons_32
|
||||
text: "${volume_minus_icon}"
|
||||
on_press:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_down
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
|
||||
# set vol
|
||||
- slider:
|
||||
id: media_player_volume_slider
|
||||
bg_color: color_slate_blue_gray
|
||||
bg_opa: 100%
|
||||
align: RIGHT_MID
|
||||
x: -60
|
||||
width: 200
|
||||
height: 10
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
indicator:
|
||||
bg_color: color_misty_blue
|
||||
knob:
|
||||
bg_color: color_misty_blue
|
||||
on_release:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_set
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
volume_level: !lambda 'return float(x) / 100.0;'
|
||||
|
||||
# vol up
|
||||
- label:
|
||||
id: media_player_vol_up_label
|
||||
x: -10
|
||||
align: RIGHT_MID
|
||||
text_color: color_steel_blue
|
||||
text_font: icons_32
|
||||
text: "${volume_plus_icon}"
|
||||
on_press:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_up
|
||||
data:
|
||||
entity_id: "${media_player_entity}"
|
||||
|
||||
# Media player name
|
||||
- obj:
|
||||
x: -20
|
||||
y: 400
|
||||
width: 360
|
||||
height: 60
|
||||
align: TOP_RIGHT
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 20%
|
||||
border_opa: TRANSP
|
||||
shadow_opa: TRANSP
|
||||
radius: 10
|
||||
widgets:
|
||||
- label:
|
||||
id: media_player_name_label
|
||||
align: CENTER
|
||||
long_mode: DOT
|
||||
text_color: color_misty_blue
|
||||
text_font: nunito_16
|
||||
text: "Friendly name"
|
||||
|
||||
# Return
|
||||
- button:
|
||||
x: 20
|
||||
y: 400
|
||||
width: 60
|
||||
height: 60
|
||||
align: TOP_LEFT
|
||||
bg_color: color_steel_blue
|
||||
bg_opa: 20%
|
||||
border_opa: TRANSP
|
||||
shadow_opa: TRANSP
|
||||
radius: 10
|
||||
widgets:
|
||||
- label:
|
||||
align: CENTER
|
||||
text_font: icons_28
|
||||
text_color: color_misty_blue
|
||||
text: "${exit_icon}"
|
||||
on_press:
|
||||
- lvgl.page.show: devices_page
|
||||
- lvgl.widget.show: menu_controls_main
|
||||
|
||||
text_sensor:
|
||||
- platform: homeassistant
|
||||
id: media_player_state
|
||||
entity_id: "${media_player_entity}"
|
||||
on_value:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return x == "paused";'
|
||||
then:
|
||||
- lvgl.label.update:
|
||||
id: media_player_state_label
|
||||
x: 0
|
||||
text: "${play_icon}"
|
||||
else:
|
||||
- lvgl.label.update:
|
||||
id: media_player_state_label
|
||||
x: 0
|
||||
text: "${pause_icon}"
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_cover
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: entity_picture
|
||||
on_value:
|
||||
- lambda: |-
|
||||
id(pending_cover_url) = x;
|
||||
- script.execute: update_cover_script
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_title_sensor
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: media_title
|
||||
on_value:
|
||||
- delay: 1s
|
||||
- lvgl.label.update:
|
||||
id: media_player_title_label
|
||||
text: !lambda return x;
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_artist_sensor
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: media_artist
|
||||
on_value:
|
||||
- delay: 1s
|
||||
- lvgl.label.update:
|
||||
id: media_player_artist_label
|
||||
text: !lambda return x;
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_repeat
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: repeat
|
||||
on_value:
|
||||
- lambda: |-
|
||||
id(pending_repeat_value) = x;
|
||||
- script.execute: update_repeat_mode_script
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_friendly_name
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: friendly_name
|
||||
on_value:
|
||||
- lvgl.label.update:
|
||||
id: media_player_name_label
|
||||
text: !lambda return x;
|
||||
|
||||
sensor:
|
||||
- platform: homeassistant
|
||||
id: media_player_volume_level
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: volume_level
|
||||
on_value:
|
||||
- lvgl.slider.update:
|
||||
id: media_player_volume_slider
|
||||
value: !lambda 'return int(x * 100);'
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_media_duration
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: media_duration
|
||||
on_value:
|
||||
- lambda: |-
|
||||
lv_slider_set_range(id(media_player_duration_pos_slider), 0, x);
|
||||
|
||||
- platform: homeassistant
|
||||
id: media_player_media_position
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: media_position
|
||||
on_value:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return !id(duration_slider_user_interaction);'
|
||||
then:
|
||||
- lvgl.slider.update:
|
||||
id: media_player_duration_pos_slider
|
||||
value: !lambda return x;
|
||||
|
||||
|
||||
binary_sensor:
|
||||
- platform: homeassistant
|
||||
id: media_player_is_volume_muted
|
||||
entity_id: "${media_player_entity}"
|
||||
attribute: is_volume_muted
|
||||
on_state:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return x;'
|
||||
then:
|
||||
- lvgl.label.update:
|
||||
id: media_player_mute_label
|
||||
text: "${volume_off_icon}"
|
||||
else:
|
||||
- lvgl.label.update:
|
||||
id: media_player_mute_label
|
||||
text: "${volume_on_icon}"
|
||||
|
||||
online_image:
|
||||
- url: "https://www.example.com/example.jpeg"
|
||||
format: JPEG
|
||||
type: RGB565
|
||||
resize: 120x120
|
||||
id: media_image_jpeg
|
||||
on_download_finished:
|
||||
- lvgl.obj.update:
|
||||
id: media_cover
|
||||
bg_image_src: media_image_jpeg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user