summaryrefslogtreecommitdiff
path: root/examples/gtk3/lua/media-player/widget/MediaPlayer.lua
blob: fbad3e045f42e98fb1d9ad304c1349ffffd0d6a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local astal = require("astal")

local Astal = astal.require("Astal", "3.0")

local bind = astal.bind
local Widget = require("astal.gtk3.widget")
local lookup_icon = Astal.Icon.lookup_icon

local map = require("lib").map

local Mpris = astal.require("AstalMpris")

---@param length integer
local function length_str(length)
	local min = math.floor(length / 60)
	local sec = math.floor(length % 60)

	return string.format("%d:%s%d", min, sec < 10 and "0" or "", sec)
end

local function MediaPlayer(player)
	local title = bind(player, "title"):as(
		function(t) return t or "Unknown Track" end
	)

	local artist = bind(player, "artist"):as(
		function(a) return a or "Unknown Artist" end
	)

	local cover_art = bind(player, "cover-art"):as(
		function(c) return string.format("background-image: url('%s');", c) end
	)

	local player_icon = bind(player, "entry"):as(
		function(e) return lookup_icon(e) and e or "audio-x-generic-symbolic" end
	)

	local position = bind(player, "position"):as(
		function(p) return player.length > 0 and p / player.length or 0 end
	)

	local play_icon = bind(player, "playback-status"):as(
		function(s)
			return s == "PLAYING" and "media-playback-pause-symbolic"
				or "media-playback-start-symbolic"
		end
	)

	return Widget.Box({
		class_name = "MediaPlayer",
		Widget.Box({
			class_name = "cover-art",
			css = cover_art,
		}),
		Widget.Box({
			vertical = true,
			Widget.Box({
				class_name = "title",
				Widget.Label({
					ellipsize = "END",
					hexpand = true,
					halign = "START",
					label = title,
				}),
				Widget.Icon({
					icon = player_icon,
				}),
			}),
			Widget.Label({
				halign = "START",
				valign = "START",
				vexpand = true,
				wrap = true,
				label = artist,
			}),
			Widget.Slider({
				visible = bind(player, "length"):as(
					function(l) return l > 0 end
				),
				on_dragged = function(event)
					player.position = event.value * player.length
				end,
				value = position,
			}),
			Widget.CenterBox({
				class_name = "actions",
				Widget.Label({
					hexpand = true,
					class_name = "position",
					halign = "START",
					visible = bind(player, "length"):as(
						function(l) return l > 0 end
					),
					label = bind(player, "position"):as(length_str),
				}),
				Widget.Box({
					Widget.Button({
						on_clicked = function() player:previous() end,
						visible = bind(player, "can-go-previous"),
						Widget.Icon({
							icon = "media-skip-backward-symbolic",
						}),
					}),
					Widget.Button({
						on_clicked = function() player:play_pause() end,
						visible = bind(player, "can-control"),
						Widget.Icon({
							icon = play_icon,
						}),
					}),
					Widget.Button({
						on_clicked = function() player:next() end,
						visible = bind(player, "can-go-next"),
						Widget.Icon({
							icon = "media-skip-forward-symbolic",
						}),
					}),
				}),
				Widget.Label({
					class_name = "length",
					hexpand = true,
					halign = "END",
					visible = bind(player, "length"):as(
						function(l) return l > 0 end
					),
					label = bind(player, "length"):as(
						function(l) return l > 0 and length_str(l) or "0:00" end
					),
				}),
			}),
		}),
	})
end

return function()
	local mpris = Mpris.get_default()

	return Widget.Box({
		vertical = true,
		bind(mpris, "players"):as(
			function(players) return map(players, MediaPlayer) end
		),
	})
end