-
Notifications
You must be signed in to change notification settings - Fork 2
/
spotify_widget.lua
executable file
·412 lines (363 loc) · 13.9 KB
/
spotify_widget.lua
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
local awful = require("awful")
local watch = require("awful.widget.watch")
local wibox = require("wibox")
local beautiful = require("beautiful")
local utils = require("utils")
local gears = require("gears")
local utils = require("utils")
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi
local spotify = {}
local dir = gears.filesystem.get_configuration_dir ()
local icons = {}
icons.spotify_play_button_icon = dir.."spawtify/icons/play-spotify.png" or beautiful.spotify_play_button_icon
icons.spotify_pause_button_icon = dir.."spawtify/icons/pause-spotify.png" or beautiful.spotify_pause_button_icon
icons.spotify_prev_button_icon = dir.."spawtify/icons/previous-spotify.png" or beautiful.spotify_prev_button_icon
icons.spotify_next_button_icon = dir.."spawtify/icons/next-spotify.png" or beautiful.spotify_next_button_icon
icons.spotify_icon = dir.."spawtify/icons/spotify-spotify.png" or beautiful.spotify_icon
icons.error_icon = dir.."spawtify/icons/ghost.png" or beautiful.spotify_error_icon
local spotify_commands = {}
spotify_commands.status = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'PlaybackStatus'|egrep -A 1 \"string\"|cut -b 26-|cut -d '\"' -f 1|egrep -v ^$"
spotify_commands.toggle = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
spotify_commands.prev = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous"
spotify_commands.next = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next"
spotify_commands.song = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata'|egrep -A 1 \"title\"|egrep -v \"title\"|cut -b 44-|cut -d '\"' -f 1|egrep -v ^$"
spotify_commands.album = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata'|egrep -A 1 \"album\"|egrep -v \"album\"|cut -b 44-|cut -d '\"' -f 1|egrep -v ^$"
spotify_commands.artist = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata'|egrep -A 2 \"artist\"|egrep -v \"artist\"|egrep -v \"array\"|cut -b 27-|cut -d '\"' -f 1|egrep -v ^$"
spotify_commands.artwork = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata'|egrep -A 1 \"artUrl\"|egrep -v \"artUrl\"|cut -b 44-|cut -d '\"' -f 1|egrep -v ^$"
local button_size
local width
local height
local old_title
local changed = false
local playing = false
local art = false
local art_path = dir .."spawtify/.cache/artwork"
local widget_geometry = {}
local artwork = wibox.widget.imagebox()
artwork.clip_shape = utils.rrect(beautiful.border_radius or 5)
local spotify_icon = wibox.widget.imagebox()
spotify_icon.forced_width = dpi(30)
spotify_icon.forced_height = dpi(30)
local spotify_icon_onclick = gears.table.join(
awful.button({ }, 1,
function()
awful.spawn("killall lightdm")
awesome.restart()
check_for_updates()
end
)
)
spotify_icon:buttons(spotify_icon_onclick)
local title = wibox.widget.textbox("Title")
title.align = center
local album = wibox.widget.textbox("Album")
album.align = center
local artist = wibox.widget.textbox("Artist")
artist.align = center
local toggle_button = wibox.widget.imagebox()
function addSongData()
local song_data = wibox.widget({
{
title,
halign = 'center',
widget = wibox.container.place,
},
--utils.pad_height(2),
{
album,
halign = 'center',
widget = wibox.container.place,
},
{
artist,
halign = 'center',
widget = wibox.container.place,
},
layout = wibox.layout.fixed.vertical,
})
return song_data
end
function set_toggle_image(toggle)
playing = not playing
if playing then
toggle.image = icons.spotify_pause_button_icon
else
toggle.image = icons.spotify_play_button_icon
end
end
function addButtons()
-- make the toggle button
toggle_button.forced_height = button_size
toggle_button.forced_width = button_size
-- make the next button
local next_button = wibox.widget.imagebox(icons.spotify_next_button_icon)
next_button.forced_height = button_size
next_button.forced_width = button_size
-- make the prev button
local prev_button = wibox.widget.imagebox(icons.spotify_prev_button_icon)
prev_button.forced_height = button_size
prev_button.forced_width = button_size
local toggle_onclick = gears.table.join(
awful.button({ }, 1,
function()
awful.spawn(spotify_commands.toggle)
set_toggle_image(toggle_button)
end
)
)
toggle_button:buttons(toggle_onclick)
local next_onclick = gears.table.join(
awful.button({ }, 1,
function()
awful.spawn(spotify_commands.next)
check_for_updates()
end
)
)
next_button:buttons(next_onclick)
local prev_onclick = gears.table.join(
awful.button({ }, 1,
function()
awful.spawn(spotify_commands.prev)
check_for_updates()
end
)
)
prev_button:buttons(prev_onclick)
local put_buttons_together = wibox.widget({
{
prev_button,
toggle_button,
next_button,
layout = wibox.layout.flex.horizontal,
spacing = button_size,
},
halign = 'center',
widget = wibox.container.place,
})
return put_buttons_together
end
--[[-----------------------------------------
Artwork Functions
]]-------------------------------------------
function initArtwork()
artwork.image = icons.error_icon
artwork.forced_height = height*0.4
artwork.forced_width = width*0.6
artwork.opacity = 0.3
artwork.resize = true
end
function getArtwork()
if art then
return artwork
else
return nil
end
end
function setArtwork(empty)
if empty then
artwork.opacity = 0.3
artwork.resize = true
artwork.image = icons.error_icon
else
artwork.opacity = 1
artwork.resize = false
artwork.image = art_path
end
end
--[[-----------------------------------------]]
spotify.widget = function(o)
awful.spawn("mkdir -p"..dir.."spawtify/.cache")
local s = o.screen
width = dpi(360) or o.width
height = dpi(280) or o.height
button_size = width * 0.1
art = o.artwork or false
if art then
initArtwork()
height = dpi(440) or o.height
end
local song_data = addSongData()
local buttons = addButtons()
title.font = beautiful.titlefont.." "..dpi(13) or beautiful.font
title.forced_height = dpi(45)
--title.ellipsize = "end"
album.font = beautiful.fontname.." "..dpi(7) or beautiful.font
artist.font = beautiful.fontname.." "..dpi(8) or beautiful.font
spotify_icon.image = icons.spotify_icon
s.spotify_widget = wibox({
screen = s,
visible = true,
width = width,
height = height,
bg = "#00000000", -- make the wibox itself fully transparent (and then we'll draw the widget inside it)
shape = gears.shape.rectangle, -- make the `wibox` a rectangle
type = "dock", -- this should tell compton (or the compositor you're using, that it doesn't want shadows around it.
-- if you still see the transparent rectangle with the shadows and it looks weird, you should configure compton to
-- not draw shadows on windows of type "dock"
ontop = true,
})
s.spotify_widget:setup({
{
{
spotify_icon,
left = dpi(12),
top = dpi(12),
bottom = dpi(3),
layout = wibox.container.margin,
},
--utils.pad_height(8),
{
getArtwork(),
halign = 'center',
widget = wibox.container.place,
},
utils.pad_height(dpi(4)),
song_data,
utils.pad_height(dpi(4)),
buttons,
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.background,
bg = "#000000" or o.fg,
-- and we do rounded corners here.
-- This way AwesomeWM can apply anti-aliasing, since it's between two of its own shapes:
-- the transparent rectangular wibox
-- and this rounded rectangle on top of it
shape = utils.rrect(beautiful.borderradius),
})
local bottom_margin = o.bottom_margin or dpi(180)
utils.relative_position(s.spotify_widget, "bottom", bottom_margin)
utils.relative_position(s.spotify_widget, "right", -10)
widget_geometry.x = s.spotify_widget.x
widget_geometry.y = s.spotify_widget.y
-- init_status()
force_update_widget()
end
-- check continously every 'artwork_callback_count' seconds for 'artwork_callback_count' * 'artwork_callback_timer' seconds
local artwork_callback_timer = 1
local artwork_callback_count = 3
--local artwork_timer = gears.timer.start_new(2.5, artworkCallback)
-- check pauseplay status has changed, and change icon accordingly.
function pause_play_check()
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.status, function(out)
if string.match(out, "Playing") then
playing = true
toggle_button.image = icons.spotify_pause_button_icon
elseif string.match(out, "Paused") then
playing = false
toggle_button.image = icons.spotify_play_button_icon
else
playing = -1
return
end
end)
end)
end
-- force update
function force_update_widget()
pause_play_check()
-- spotify not running/dbus error
if playing==-1 then return end
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.song, function(out)
old_title = out
title:set_markup (utils.colorize_text(out,"#ffffff"))
data_changed()
end)
end)
end
--update if changes
function check_for_updates()
pause_play_check()
-- spotify not running/dbus error
if playing==-1 then return end
-- function called before widget was completely initialized.
-- the assumption is that force_update_widget MUST be called at least once before this function can be called
if not old_title then return end
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.song, function(out)
-- if previously saved title is not same as output, then song has changed.
if old_title ~= out then
old_title = out
title:set_markup (utils.colorize_text(out,"#ffffff"))
setArtwork(true)
data_changed()
end
end)
end)
end
function data_changed()
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.album, function(out)
album:set_markup ("<span foreground='#ffffffAA'><i>" .. out .. "</i></span>")
end)
end)
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.artist, function(out)
artist:set_markup ("<span foreground='#ffffff'>by <b>" .. out .. "</b></span>")
naughty.noVtify({text="cmd: "..TOP_CMD})
end)
end)
if art then
awful.spawn.easy_async_with_shell(command, function()
awful.spawn.easy_async_with_shell(spotify_commands.artwork, function(out)
local cmd = "wget -O "..dir.."spawtify/.cache/artwork "..out
awful.spawn(cmd)
--gears.timer.weak_start_new(artwork_callback_timer, artworkCallback):stop()
gears.timer.weak_start_new(artwork_callback_timer, artworkCallback):start()
end)
end)
end
collectgarbage()
end
function artworkCallback()
artwork_callback_count = artwork_callback_count-1
if artwork_callback_count > 0 then
setArtwork(false)
return true
else
artwork_callback_count = 3
collectgarbage()
return false
end
end
--watch(spotify_commands.song, 5, check_for_updates, artwork)
local widget_update = gears.timer{
timeout = 5,
call_now = false,
callback = function()
check_for_updates()
end
}
widget_update:start()
spotify.toggle = function()
for s in screen do
if s.spotify_widget then
s.spotify_widget.visible = not s.spotify_widget.visible
end
if s.spotify_widget.visible then
check_for_updates()
widget_update:start()
awful.spawn("glava")
else
awful.spawn("killall glava")
widget_update:stop()
end
end
end
spotify.setVisualizer = function(client)
client.x = widget_geometry.x +5
client.width = dpi(345)
client.y = widget_geometry.y - 190
gears.timer.delayed_call(function()
gears.surface.apply_shape_bounding(client, gears.shape.rectangle)
end)
client.floating = true
client.focusable = false
client.ontop = true
client.sticky = true
end
return spotify