-
Notifications
You must be signed in to change notification settings - Fork 28
/
kunst
executable file
·261 lines (216 loc) · 7.94 KB
/
kunst
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
#!/usr/bin/env bash
# ┬┌─┬ ┬┌┐┌┌─┐┌┬┐
# ├┴┐│ ││││└─┐ │
# ┴ ┴└─┘┘└┘└─┘ ┴
# Created by Siddharth Dushantha
#
# Dependencies: nsxiv, imagemagick, bash, ffmpeg, mpc, jq, mpd
VERSION=1.3.4
TMP=${TMPDIR:-/tmp}
COVER=$TMP/kunst.jpg
MUSIC_DIR="${KUNST_MUSIC_DIR:-~/Music}"
SIZE="${KUNST_SIZE:-250x250}"
POSITION="${KUNST_POSITION:-+0+0}"
ONLINE_ALBUM_ART=""
PROG_NAME=$(basename "$0")
show_help() {
printf "%s" "\
usage: kunst [-h|--help] [--size \"px\"] [--position \"+x+y\"]
[--music_dir \"path/to/dir\"] [--verbose] [--version]
┬┌─┬ ┬┌┐┌┌─┐┌┬┐
├┴┐│ ││││└─┐ │
┴ ┴└─┘┘└┘└─┘ ┴
Download and display album art or display embedded album art
optional arguments:
-h, --help show this help message and exit
--size what size to display the album art in
--position the position where the album art should be displayed
--music_dir the music directory which MPD plays from
--verbose show the output
--force-online force getting cover from the internet
--version show the version of kunst you are using
"
}
log() {
[ "$VERBOSE" ] && echo "$PROG_NAME: $1"
}
logError() {
echo "$PROG_NAME: $1" >&2
exit 1
}
# Parse the arguments
options=$(getopt -o h --long 'position:,size:,music_dir:,version,force-online,verbose,help' -- "$@")
eval set -- "$options"
while true; do
case "$1" in
--size)
shift;
SIZE=$1
;;
--position)
shift;
POSITION=$1
;;
--music_dir)
shift;
MUSIC_DIR=$1
;;
-h|--help)
show_help
exit
;;
--version)
echo $VERSION
exit
;;
--force-online)
ONLINE_ALBUM_ART=true
;;
--verbose)
VERBOSE=true
;;
--)
shift
break
;;
esac
shift
done
# This is a base64 endcoded image which will be used if
# the file does not have an emmbeded album art.
# The image is an image of a music note
read -r -d '' MUSIC_NOTE << EOF
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJESURBVGhD7Zg/axRRFMVXAtpYphEVREKClnHfJI0MmReSfAC3tRejhaBgo70fwN7aD2BvEU0gfztbu5AqMxNjoVnvG87KZXy7z5m5dxLI/OCw8Pade+7M3n3Dbq+jo6OjY8RwMJhKk+hhlph3eRJ9w/LF5jCOr1PTj6jpD7mNjkjDkbDl4vFjpX87teZJlkSfSD9501zYfv5QJ1fyZHGexuJtZs12ZqMzX8NlwX4+nK3NXMutWaOm39Nd/u5rMCSUao80fjBNwY+p8Y+krNxQVaGsLsfWzFLYS2r4M30Rf5WbaCJE6OILlhIidPEFSwkRuviCpYQIXXzB1WX26bR6ky4v3OPriNCFB1YRHa079Pr6eKk/h1IFfA+WdOGBk+QeXtT0Ft3pV6e2fxf2f+AeLOnCA8tC0xv09H1xGi/cgWUi3I8lXXigEzX8u3gmWPP8JI5uYdt/w2thSRceSM0/zVfnb+CtWvB6WNJFOlC6XhDpQOl6QaQDpesFkQ6UrhdEOlC6XpA6gcPB/avumKXnxCadXHkha766tTr1GlE18CRZvEmN7nHfOMGiS5XA4mdmYg64Z5Jg06VKYHlEQoKtOVIz6zx8f0iwNUNyZt2F+3zjBFt9pGe22gWYFLb6lEckJNjGUmWEssR8ga0+0jNL9Z75fD7Rp7UOW32kZxb/1u37vFyUu+sODtjqozGzxaFADfprFM3vuD3Y3gytmf17LJPHXbgTNb5BWhe58yNan1lpWp9ZDVqdWS1am9mOjo7LRq/3B1ESKyYUVquzAAAAAElFTkSuQmCC
EOF
is_connected() {
# Check if internet is connected. We are using api.deezer.com to test
# if the internet is connected because if api.deezer.com is down or
# the internet is not connected this script will work as expected
if ping -q -c 1 -W 1 api.deezer.com >/dev/null; then
connected=true
else
log "unable to check online for the album art"
connected=false
fi
}
get_cover_online() {
# Check if connected to internet
is_connected
if [ "$connected" == false ];then
ARTLESS=true
return
fi
# If the current playing song ends with .mp3 or something similar, remove
# it before searching for the album art because including the file extension
# reduces the chance of good results in the search query
QUERY=$(mpc current | sed 's/\.[^.]*$//' | iconv -t ascii//TRANSLIT -f utf8)
# Try to get the album cover online from api.deezer.com
API_URL="https://api.deezer.com/search/autocomplete?q=$QUERY" && API_URL=${API_URL//' '/'%20'}
log "fetching $API_URL"
# Extract the albumcover from the json returned
JSON=$(curl -s "$API_URL")
ALBUM=$(echo "$JSON" | jq -r '.tracks.data[0].album.picture_big' | sed 's/null//');
ARTIST=$(echo "$JSON" | jq -r '.tracks.data[0].artist.picture_big' | sed 's/null//');
IMG_URL="${ALBUM:-$ARTIST}"
if [ "$IMG_URL" = '' ] || [ "$IMG_URL" = 'null' ];then
log "cover not found online"
ARTLESS=true
else
log "cover found online"
curl -o "$COVER" -s "$IMG_URL"
ARTLESS=false
fi
}
find_album_art(){
# Check if the user wants to get the album art from the internet,
# regardless if the current song has an embedded album art or not
if [ ! -z "$ONLINE_ALBUM_ART" ]; then
log "getting cover from internet"
get_cover_online
return
fi
# Extract the album art from the mp3 file and dont show the messsy
# output of ffmpeg
ffmpeg -i "$MUSIC_DIR$(mpc current -f %file%)" "$COVER" -y &> /dev/null
# Get the status of the previous command
STATUS=$?
# Check if the file has a embbeded album art
if [ "$STATUS" -eq 0 ];then
log "extracted album art"
ARTLESS=false
else
DIR="$MUSIC_DIR$(dirname "$(mpc current -f %file%)")"
log "inspecting $DIR"
# Check if there is an album cover/art in the folder.
# Look at issue #9 for more details
for CANDIDATE in "$DIR/cover."{png,jpg,webp}; do
if [ -f "$CANDIDATE" ]; then
STATUS=0
ARTLESS=false
convert "$CANDIDATE" $COVER &> /dev/null
log "found cover.png"
fi
done
fi
if [ "$STATUS" -ne 0 ];then
log "file does not have an album art"
get_cover_online
fi
}
update_cover() {
find_album_art
if [ "$ARTLESS" == false ]; then
convert "$COVER" -resize "$SIZE" "$COVER" &> /dev/null
log "resized album art to $SIZE"
fi
}
pre_exit() {
# Get the proccess ID of kunst and kill it.
# We are dumping the output of kill to /dev/null
# because if the user quits nsxiv before they
# exit kunst, an error will be shown
# from kill and we dont want that
kill -9 "$(cat "$TMP/kunst.pid")" &>/dev/null
}
main() {
dependencies=(nsxiv convert bash ffmpeg mpc jq mpd)
for dependency in "${dependencies[@]}"; do
type -p "$dependency" &>/dev/null || {
logError "could not find '${dependency}', is it installed?"
}
done
# Flag to run some commands only once in the loop
FIRST_RUN=true
while true; do
update_cover
if [ "$ARTLESS" == true ];then
# Dhange the path to COVER because the music note
# image is a png not jpg
COVER=$TMP/kunst.png
# Decode the base64 encoded image and save it
# to /tmp/kunst.png
echo "$MUSIC_NOTE" | base64 --decode > "$COVER"
fi
log "swapped album art to $(mpc current)"
if [ "$FIRST_RUN" == true ]; then
FIRST_RUN=false
# Display the album art using nsxiv
nsxiv -g "$SIZE$POSITION" -b "$COVER" -N "Kunst" &
# Save the process ID so that we can kill
# nsxiv when the user exits the script
echo $! >"$TMP/kunst.pid"
fi
# Waiting for an event from mpd; play/pause/next/previous
# this is lets kunst use less CPU :)
while true; do
mpc idle player &>/dev/null && (mpc status | grep "\[playing\]" &>/dev/null) && break
done
log "received event from mpd"
done
}
# Disable CTRL-Z because if we allowed this key press,
# then the script would exit but, nsxiv would still be
# running
trap "" SIGTSTP
trap pre_exit EXIT
main