forked from phoenixbyrd/Screensavers
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgui
executable file
·348 lines (285 loc) · 11.8 KB
/
gui
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
#!/bin/bash
DIRECTORY="$(dirname "$0")"
closewindows() {
kill $pid1 2>/dev/null || echo 'pid1 not found'
kill $(cat "$DIRECTORY/pid2" 2>/dev/null) 2>/dev/null || echo 'pid2 not found'
}
error() {
echo -e "\e[91m$1\e[39m" 1>&2
closewindows
#run cleanup function
cleanup
kill -w -s TERM $TOP_PID
}
export GDK_BACKEND=x11 #fix window placement on wayland
trap closewindows EXIT
export TOP_PID=$$
#list of subdirectory names. hidden directories not shown.
list="$(ls "$DIRECTORY"/*/ -d | sed "s|$DIRECTORY/||g" | sed -e 's-/$--')"
#clear currentclick
"$DIRECTORY"/clickhandler
checkimages() { #resize all *.png images to 500px wide
#list of images found in screensaver folders - full paths
imagelist="$(ls "$DIRECTORY"/*/*.png)"
PREIFS="$IFS"
IFS=$'\n'
for image in $imagelist ;do
#if backup image doesn't exist and image is not 500 pixel wide
sc_original_path="$(dirname "$image")/screenshot-original.png"
if [ ! -f "$sc_original_path" ];then
#backup the image
mv -f "$image" "$sc_original_path"
if ! command -v identify >/dev/null || ! command -v convert >/dev/null ;then
error "The identify and convert commands are necessary to resize screenshots.\nIf you are on a debian-based system, this should work: 'sudo apt install imagemagick'"
fi
if [ "$(identify -format '%w' "$sc_original_path")" != 500 ];then
#resize the image to 500 pixels wide, and save it to screenshot.png
convert "$sc_original_path" -resize 500x "$(dirname "$image")/screenshot.png"
fi
else
#image is already 500px wide and/or backup image exists
true
fi
done
IFS="$PREIFS"
}
checkimages
cleanup() {
rm -f "$DIRECTORY/window2-exitcode" "$DIRECTORY/pid2" "$DIRECTORY/pid1" "$DIRECTORY/window1-exitcode" "$DIRECTORY/currentclick"
}
#run cleanup function
cleanup
#check for dependencies
if ! command -v yad >/dev/null ;then
error "The YAD dialog program must be installed.\nIf you are on a debian-based system, this should work: 'sudo apt install yad'"
elif ! command -v wine >/dev/null ;then
error "Wine must be installed.\nUse Pi-Apps to install Wine.\n/~https://github.com/Botspot/pi-apps"
elif ! command -v xdpyinfo >/dev/null ;then
error "In order to determine the dimensions of your screen, xdpyinfo must be installed.\nIf you are on a debian-based system, this should work: 'sudo apt install x11-utils'"
elif ! command -v xprintidle >/dev/null ;then
error "In order to measure inactivity time, xprintidle is necessary.\nIf you are on a debian-based system, this should work: 'sudo apt install xprintidle'"
fi
#check for updates
if [ ! -f "${DIRECTORY}/no-update-check" ];then
cd "$DIRECTORY"
localhash="$(git rev-parse HEAD)"
cd
latesthash="$(git ls-remote /~https://github.com/Botspot/Screensavers HEAD | awk '{print $1}')"
if [ "$localhash" != "$latesthash" ] && [ ! -z "$latesthash" ] && [ ! -z "$localhash" ];then
echo -e "Updating..."
git pull
echo -e "To disable this, create a file named: '${DIRECTORY}/no-update-check'\n"
fi
fi
#create menu launcher
if [ ! -f ~/.local/share/applications/windows-screensavers.desktop ];then
echo "[Desktop Entry]
Exec=$DIRECTORY/gui
Icon=xscreensaver
Terminal=false
Name=Windows Screensavers
Comment=Select and configure Windows screensavers that run on your Pi with Wine
Type=Application
Categories=Settings;DesktopSettings;Security;X-XFCE;" > ~/.local/share/applications/windows-screensavers.desktop
fi
#Screen dimension stuff
{
screen_width="$(xdpyinfo | grep 'dimensions:' | tr 'x' '\n' | tr ' ' '\n' | sed -n 7p)"
screen_height="$(xdpyinfo | grep 'dimensions:' | tr 'x' '\n' | tr ' ' '\n' | sed -n 8p)"
#total dimensions for both windows side by side
height=450
width=700
yoffset=$(((screen_height/2)-(height/2)))
#width of first window
width1=200
#width of second window
width2=$((width - width1))
#screen offsets for window 1
xoffset1=$(((screen_width/2)-(width/2)))
#screen offsets for window 2
xoffset2=$(((screen_width/2)-(width/2)+width1))
}
#Deleting this file will kill the script
echo '' > "$DIRECTORY/closefile"
(while [ -f "$DIRECTORY/closefile" ];do
sleep 1
done
error "exited" ) &
#screensaver list on the left, run in the background
(echo "$list" | yad --list --geometry=${width1}x${height}+${xoffset1}+${yoffset} \
--class screensaver --window-icon=xscreensaver --title=' ' \
--no-headers --column=item --select-action="$DIRECTORY"/clickhandler --no-buttons &
pid1=$!
echo $pid1 > "$DIRECTORY/pid1"
wait $pid1
echo $? > "$DIRECTORY/window1-exitcode"
rm -f "$DIRECTORY/closefile") &
#wait for pid1 file to exist (wait for window1 to launch)
while [ ! -f "$DIRECTORY/pid1" ];do
sleep 0.1
done
pid1="$(cat "$DIRECTORY/pid1")"
#wait until a screensaver is clicked before launching second window
echo -n '' > "${DIRECTORY}/currentclick"
currentclick="$(read line < <(tail -f --retry "${DIRECTORY}/currentclick" 2>/dev/null) ; echo "$line")"
delay="$(cat "${DIRECTORY}/delay")"
while true;do #main loop that runs right pane forever
currentclick="$(cat "${DIRECTORY}/currentclick")"
#refreshes window2 each time a new list item is selected
output="$(
while true;do
checkimages &
#screensaver preview window
[ ! -z "$pid2" ] && kill $pid2 # kill previous instance if it exists
rm -f "$DIRECTORY/window2-exitcode"
#display simplified window if only run.sh exists
if [ -f "$DIRECTORY/$currentclick/install.sh" ];then
(
#display warning on wayland
if [ ! -z "$WAYLAND_DISPLAY" ];then
text=(--field='Warning: On Wayland the screensaver cannot start when computer is inactive! Clicking OK or Apply will not work. Just click Preview.:LBL' '')
else
text=()
fi
yad --geometry=${width2}x${height}+${xoffset2}+${yoffset} --title="$currentclick" --window-icon=xscreensaver --class screensaver \
--form --columns=2 --separator='\n' \
--field="Wait: ":NUM "$delay"'!1..60' --field="Settings...!!Installs the screensaver, then runs its settings.sh script.":FBTN "$DIRECTORY/settings" \
"${text[@]}" \
--field="minutes":RO "" --field="Preview!!Installs the screensaver, then runs it."$'\n'"The screensaver service won't be modified.":FBTN "$DIRECTORY/preview" \
"$([ -f "$DIRECTORY/$currentclick/screenshot.png" ] && echo --image="$DIRECTORY/$currentclick/screenshot.png")" --image-on-top \
--button="OK!!Installs the screensaver, then generates the screensaver service."$'\n'"The list of screensavers will close when finished.:0" --button="Cancel!!Don't make any changes.:2" --button="Apply!!Installs the screensaver, then generates the screensaver service."$'\n'"This window will reappear when finished.:4" &
pid2=$!
echo "$pid2" > "$DIRECTORY/pid2"
#write exit code to file as long as it was not the termination exit code. (143)
wait $pid2 ; exitcode2=$?
if [ $exitcode2 != 143 ];then
echo $exitcode2 > "$DIRECTORY/window2-exitcode"
fi
) &
else #install.sh does not exist, assume run.sh exists
(
yad --geometry=${width2}x${height}+${xoffset2}+${yoffset} --title="$currentclick" --window-icon=xscreensaver \
"$([ -f "$DIRECTORY/$currentclick/screenshot.png" ] && echo --image="$DIRECTORY/$currentclick/screenshot.png")" --image-on-top \
--button="Cancel!!Don't make any changes.:2" --button="Run script!!"${DIRECTORY}/$currentclick/run.sh":6" &
pid2=$!
echo "$pid2" > "$DIRECTORY/pid2"
#write exit code to file as long as it was not the termination exit code. (143)
wait $pid2 ; exitcode2=$?
if [ $exitcode2 != 143 ];then
echo $exitcode2 > "$DIRECTORY/window2-exitcode"
fi
) &
fi
sleep 0.5
pid2="$(cat "$DIRECTORY/pid2")"
#wait until selection in window1 changes
currentclick="$(while read line ;do [ "$line" != "$currentclick" ] && break ; done < <(tail -f --retry "${DIRECTORY}/currentclick" 2>/dev/null) ; echo "$line")"
if [ -f "$DIRECTORY/window2-exitcode" ];then
#if exitcode file exists, exit this while loop with that exit code.
echo "exit $(cat "$DIRECTORY/window2-exitcode")" 1>&2
exit "$(cat "$DIRECTORY/window2-exitcode")"
break
elif [ ! -f "${DIRECTORY}/currentclick" ];then
#exit if currentclick missing
exit 0
fi
done
)"
button=$?
echo "Output: ${output}EOO"
delay="$(echo "$output" | sed -n 1p)"
if [ -z "$delay" ];then
#read delay value from file if it's blank
delay="$(cat "${DIRECTORY}/delay")"
fi
echo "Delay: $delay"
currentclick="$(cat "${DIRECTORY}/currentclick")"
case $button in
1|252)
echo "User exited."
exit 0
;;
0|4)
echo "Button: OK or Apply"
if [ "$currentclick" == none ];then
echo "Removing systemd service..."
#Stop existing screensaver.service
if [ -f /etc/systemd/system/screensaver.service ]; then
echo "Stopping the service first..."
sudo systemctl stop screensaver
sudo systemctl disable screensaver
sudo rm /etc/systemd/system/screensaver.service
fi
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
else #screensaver is not 'none'
echo "Running install.sh for '$currentclick'..."
#run selected screensaver's install script
"${DIRECTORY}/$currentclick/install.sh"
echo "Creating daemon script for '$currentclick'..."
#write new delay value to file
echo "$delay" > "${DIRECTORY}/delay"
#create screensaver daemon script that waits specified amount of time
echo "#!/bin/bash
export DISPLAY=:0
while true;do
#if idle time is greater than set time, and no audio devices are playing (stackoverflow.com/a/17404952)
if [ "\$"(xprintidle) -gt $(($(cat "${DIRECTORY}/delay")*1000*60)) ] && [ -z "'"$(grep -r RUNNING /proc/asound/card*/pcm*/sub*/status)"'" ];then
"\""${DIRECTORY}/$currentclick/run.sh"\""
fi
sleep 60
done" > ~/.screensavers/daemon.sh
chmod +x ~/.screensavers/daemon.sh
#Stop existing screensaver.service
if [ -f /etc/systemd/system/screensaver.service ]; then
echo "Stopping the systemd service first..."
sudo systemctl stop screensaver
echo "Disabling service..."
sudo systemctl disable screensaver
fi
echo "Creating systemd service for '$currentclick'..."
#create the service
echo "[Unit]
Description=Screensaver
[Service]
User=pi
Type=simple
ExecStart=/bin/bash $HOME/.screensavers/daemon.sh
[Install]
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/screensaver.service >/dev/null
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
echo "Starting the service..."
sudo systemctl start screensaver
echo "Enabling the service..."
sudo systemctl enable screensaver
#print instructions
echo -e "\e[93m
Verify service is running : sudo systemctl status screensaver
Enable on startup : sudo systemctl enable screensaver
Disable on startup : sudo systemctl disable screensaver
Start screensaver service : sudo systemctl start screensaver
Stop screensaver service : sudo systemctl stop screensaver\e[39m"
fi
#if OK clicked, exit program now
if [ $button == 0 ];then
echo "OK button clicked, so exiting now"
exit 0
fi
;;
2)
echo "Button: Cancel"
exit 0
;;
6)
echo "Button: Run script"
echo "Running run.sh for '$currentclick'..."
#run selected screensaver's install script
"${DIRECTORY}/$currentclick/run.sh"
exit 0
;;
*)
error "Unknown button: $button"
;;
esac
done