-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpd.zmq
executable file
·399 lines (350 loc) · 14 KB
/
mpd.zmq
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
#!/bin/bash
#export LC_CTYPE="UTF-8"
export TERM
editscript(){
local scriptpath script path swp; scriptpath=$(realpath "$0" 2>/dev/null); script="${scriptpath##*/}"; path="${scriptpath%/*}"; swp="$path/.$script.swp"
[[ ! -e "$swp" ]] && printf "\n\n%s\n\n" "$swp" && (/usr/bin/nano "$scriptpath") && exit
printf "\n%s is already being edited.\n%s exists; try fg or look in another window.\n" "$scriptpath" "$swp"; exit ;}
[[ "$1" = @(edit|e|-e) ]] && editscript && exit
. mpdignore.functions
bold="$(tput bold)"
tput0="$(tput sgr0)"
yellow="$(tput setaf 214)"
blue="$(tput setaf 33)"
boldred="$(tput bold setaf 9)"
verbose=false
tunport="$mpdzmqtunport"
retport="$mpdzmqretport"
autosshpid="/tmp/autossh_${tunport}.pid"
ffplaypid="/tmp/ffplayzmq-$(date -Im).pid"
sinkMAC1='00:42:79:D9:B6:AF'
sinkname2='JBL Xtreme 2'
sinkMAC2='00:1F:47:9F:8C:57'
[[ "$mpdhost" = "$(hostname)" ]] && exit 1
pause(){ echo "$@" ; read -rp "contents" < /dev/tty; }
showhelp(){
cat <<EOF
Usage: $0 [OPTIONS]
A script for controlling various media and remote actions.
Options:
-e, e, edit Edit the script and exit.
--ip <remote_ip> Specify the remote IP for ZMQ communications.
--port, -p <port> Specify the remote port for ZMQ communications.
--reset, --restart Reset or restart the ZMQ service.
-v, --verbose Enable verbose output.
--quit, --exit, Stop the media player and tunnel; optionally...
q[uit], exit ...pause mpd and disconnect BT speaker.
pause Pause the media playback.
play Resume the media playback.
-h, --help, help Display this help information.
EOF
}
hr(){
local width="$(tput cols)"
# local width=${1:-${COLUMNS:-80}} # Default to 80 if COLUMNS is unset
# printf -- '%.0s—' $(seq "${1:-$COLUMNS}"); echo; }
printf -- '%.0s—' $(seq 1 "$width"); echo; }
resetzmq(){
btctlout="$(bluetoothctl disconnect "$sinkMAC1"|grep -v "Attempting to disconnect from $sinkMAC1")"
printf '\n%s%sAttempting to disconnect %s%s/%s%s:%s\n%s\n' \
"$yellow" \
"$bold" \
"$blue" \
"$sinkname1" \
"$sinkMAC1" \
"$yellow" \
"$tput0" \
"$btctlout"
printf %s\\n "$(hr)"
echo
before=before
for j in psaux pkill psaux; do
printf %s%s "$bold" "$yellow"
[[ "$j" = psaux ]] && echo "$j $before:" || echo "$j:"
printf %s "$tput0"
for i in autossh ffplay bin/mpd.zmq; do
"$j" "$i"|grep -v -- '--reset'
done
[[ "$before" = before ]] && before=after
hr
echo
done
pause "${yellow}${bold}^C to exit, [Enter] to continue.${tput0}"
hr
}
startautossh(){
#if ! ps aux | grep "[a]utossh.*-L${tunport}:localhost:${tunport}.*${mpdhost}.*-p${sshport}" > /dev/null; then #moving from ps aux to ss:
#if ! ssout=( ss -tlnp | grep -E "LISTEN.+:${tunport}.*users:\(\(\"(ssh|autossh)\",pid=[[:digit:]]+,fd=[[:digit:]]\)\)" ); then
if ! ssout=( "$(ss -tlnp | grep --color=always -E "LISTEN.+:${tunport}.*users:\(\(\"(ssh|autossh)\",pid=[[:digit:]]+,fd=[[:digit:]]\)\)")" ); then
# more permissive: if ! ss -tlnp | grep -E "LISTEN.+:${tunport}.*users:\(.*(ssh|autossh)"; then
#pause "going to start a new connection!!!!!!!!!!!!!!! ok? hit enter to continue"
autoarr=(autossh -fvN -M0 -L "${tunport}:localhost:${tunport}" "$mpdhost" -p "${sshport}")
"${autoarr[@]}"; ec="$?"; pause "error code from autossh: $ec"
if ! (( ec )); then { printf '%s[ERROR]%s unable to open the tunnel\nexit 1' "${boldred}" "$tput0"; exit 1; exit 1; }; fi
\sleep 1
autossh_pid=$(pgrep -f "autossh/autossh.*-L${tunport}:localhost:${tunport}.*${mpdhost}.*-p${sshport}")
echo "$autossh_pid" > "${autosshpid}" #this might be the right pid?
elif "${verbose:-false}"; then
printf -- 'tunnel status:\n ss -tlnp\n%s\n\n' "${ssout[@]}"
screen -ls
psaux 5555
psaux ffplay
fi
#
#Purpose of -f in autossh
#-f (fork): This flag causes autossh to fork into the background, which is often desirable if you don't want your terminal to stay tied to the process. It makes the SSH connection run in the background, so the user can continue using the terminal for other tasks. This is useful when you're scripting or need a long-running SSH session without blocking the shell.
#Why Remove -f in My Suggestion?
#When -f is used, the parent shell forks first, then autossh forks and detaches into the background. As a result, the PID you capture using $! is of the shell's child process, not the final autossh process. That's why I initially suggested removing -f, as it allows you to more reliably capture the correct autossh PID.
#
#Compensation for Removing -f:
#By removing -f, you're preventing autossh from forking into the background. To compensate for this, I added & at the end of the command:
#
#bash
#Copy code
#autossh -vN -M0 -L"${tunport}":localhost:"${tunport}" -R"${retport}":localhost:22 "${mpdhost}" -p"${sshport}" &
#This & ensures that the command runs in the background, but without the double-forking behavior that the -f flag triggers. This allows you to capture the correct autossh PID using pgrep.
#
#If You Still Want to Use -f:
#If you absolutely need the -f flag (for instance, if the behavior of autossh requires it to double-fork and detach), you can keep it, but capturing the PID becomes trickier. You'll have to rely on pgrep or ps after the process has forked into the background.
#
#Here’s how you can still use -f and capture the correct PID:
#
#bash
#Copy code
#startssh() {
# if ! ps aux | grep "[a]utossh.*-L${tunport}:localhost:${tunport}.*${mpdhost}.*-p${sshport}" > /dev/null; then
# autossh -fvN -M0 -L"${tunport}":localhost:"${tunport}" -R"${retport}":localhost:22 "${mpdhost}" -p"${sshport}"
# sleep 1 # Give autossh some time to fork and start
# autossh_pid=$(pgrep -f "autossh.*-L${tunport}:localhost:${tunport}.*${mpdhost}.*-p${sshport}")
# echo "${autossh_pid}" > "${autosshpid}"
# fi
#}
#Why This Works:
#-f is still there, so autossh will run in the background just as before.
#pgrep finds the correct autossh process after it forks, using the command-line pattern to match the process.
#This method keeps the original background behavior while ensuring you capture the right PID.
}
startffplay(){
readarray -t rmpidout < <(rm /tmp/ffplayzmq-????-??-??T??\:??-0{4,5}\:00.pid 2>&1)
for line in "${rmpidout[@]}"; do
if [[ "$line" != "rm: cannot remove '/tmp/ffplayzmq-"????\-??\-??\T??\:??\-\0?":00.pid': No such file or directory" ]]; then
echo "$line"
# else
# printf suppressed\ error\:\ %s\\n "${rmpidout[@]}"
fi
done
screen -dmS mpd.zmq sh -c \
'ffplay -autoexit -nodisp zmq:tcp://localhost:5555 -loglevel debug & echo $! > "$0"; wait' \
"${ffplaypid}"
}
stopffplay(){
printf 'Looking for open mpd.zmq screens!'
while screen -ls | grep -E '[[:digit:]]+\.mpd\.zmq'; do
screen -S mpd.zmq -X quit &>/dev/null
screen -wipe &>/dev/null
done
}
confirm(){
local ans IFS=
while read -rp "$1" -n1 ans
do
printf '\n'
case "$ans" in
[Yy]) return 0;;
[Nn]) return 1;;
esac
done
##--> confirm() <--###################################################################################
}
stopmpdzmq(){
local stopautossh=false
local stopzmqscreen=false
local nine ffplaypid
while ! "$stopautossh" || ! "$stopzmqscreen" ; do
stopffplay
local autossh_pid="$(cat "$autosshpid")"
killcmd="${nine:+$nine} $autossh_pid"
kill "$killcmd" #2>/dev/null
echo
screenlsout="$(screen -ls|grep --color=always mpd.zmq)"
if [[ "$screenlsout" && ! "$stopzmqscreen" ]]; then
if [[ "$ffplaypid" ]]; then
ffkill="${ffnine:+$ffnine} $ffplaypid"
kill "$ffkill"
ffnine="-9"
fi
printf '%s%sThe output of `screen -ls|grep mpd.zmq` should be empty: \n%s' "$bold" "$yellow" "$tput0"
hr
echo "$screenlsout"
hr
echo
confirm "Are the mpd.zmq screens closed? " && stopzmqscreen=true
ffplaypid=(ls /tmp/ffplayzmq-*)
ffplaypid="${ffplaypid[-1]}"
else
printf '%s%sThe ffplay and the mpd.zmq screen are closed.\n%s' "$bold" "$yellow" "$tput0"
hr
stopzmqscreen=true
fi
psaux5555="$(ps aux|grep --color=never "[${tunport:0:1}]${tunport:1}"|grep --color=always -E autossh\|ffplay\|"$mpdhost")"
if [[ "$psaux5555" && ! "$stopautossh" ]]; then
printf 'The output of `psaux 5555` should be empty: \n'
hr
echo "$psaux5555"
hr
echo
confirm "${yellow}${bold}Are ffplay and autossh closed? $tput0" && stopautossh=true
nine='-9'
else
printf '%s%s\nThe autossh tunnel is closed.\n%s' "$bold" "$yellow" "$tput0"
hr
stopautossh=true
fi
done
echo
if confirm "${yellow}${bold}Disconnect bluetooth speaker $sinkname1? $tput0"; then
echo
btctlout="$(bluetoothctl disconnect "$sinkMAC1")"
printf "$btctlout"|grep --color=always -E Attempting\ to\ disconnect\ from\ "$sinkMAC1"\|Successful\ disconnected
echo
fi
hr
echo
confirm "${yellow}${bold}Pause mpd on $mpdhost? $tput0" && mpctitle pause
hr
}
connectBT(){
local btctlout=("$(bluetoothctl list)")
#debug output
# echo "btctlout+=(\"$(bluetoothctl connect \"$sinkMAC1\" 2>&1)\") &&"
btctlout+=("$(bluetoothctl connect "$sinkMAC1" 2>&1)") &&
connected=yes || connected=no
#debug output
# echo "btctlout+=(\"$(bluetoothctl info "$sinkMAC1")\")"
btctlout+=("$(bluetoothctl info "$sinkMAC1")")
#debug output
# printf %s\\n%s\\n\\n "$connected" "$(declare -p btctlout)"
# this had to be added because the echo > fifo is blocking and the command will not complete until there's a reader, but that's not going to happen"
tail -f "$btctlfifo" > /dev/null &
readerpid=$!
{ echo "$connected"
declare -p btctlout
} > "$btctlfifo"
#debug output
printf '\n\n\connectBT; exit %s' "$?"
kill "$readerpid"
}
remote-zmq(){
local zmqport
local remote="$1"; shift
[[ "$1" = -@(-port|p) ]] && zmqport="$2"; shift 2
sshargs=( 'ssh' )
sshargs+=( '-t' )
[[ "$zmqport" ]] && sshargs+=( "-p$zmqport" )
sshargs+=( '--' )
sshargs+=( "$remote" )
sshargs+=( 'mpd.zmq' )
sshargs+=( "$@" )
# ssh -t "$remote" mpd.zmq "$@"
# ssh $(printf %s\ "${sshargs[@]}")
"${sshargs[@]}"
exit "$?"
}
############################################################################################################
# mpd.zmq main block
############################################################################################################
[[ "$1" = @(--help|-h|help) ]] && { showhelp; exit; }
#[[ "$1" = --port ]] && port="$2" && shift 2 && remote-zmq "$remote" "$@"
[[ "$1" = --ip ]] && remote="$2" && shift 2 && remote-zmq "$remote" "$@"
[[ "$1" = --@(reset|restart) ]] && shift && resetzmq
[[ "$1" = @(--verbose|-v) ]] && verbose=true && shift
[[ "$1" = @(--quit|--exit|q@(|uit)|exit) ]] && { stopmpdzmq; exit; }
[[ "$1" = pause ]] && { pkill -19 ffplay; exit; } # -SIGSTOP
[[ "$1" = play ]] && { pkill -18 ffplay; exit; } # -SIGCONT
verbose=true
echo "mkfifo..."
tmpdir=$(mktemp -d)
btctlfifo=$(mktemp -u "$tmpdir/fifo_XXXX")
mkfifo "$btctlfifo"
echo "check for bluetooth connection"
connected=$(bluetoothctl info "$sinkMAC1"|grep Connected|awk '{print $2}')
if [[ "$connected" = no ]]; then
connected=$(bluetoothctl info "$sinkMAC2"|grep Connected|awk '{print $2}')
sinkMAC="$sinkMAC2"
sinkname="$sinkname2"
else
sinkMAC="$sinkMAC1"
sinkname="$sinkname1"
fi
if [[ "$connected" = no ]]; then
echo "entered if portion... are you stuck? look at what's going on in connectBT&"
connectBT&
IFS= read -r connected < "$btctlfifo" # this should grab just one line (no while)
. "$btctlfifo" # rest of FIFO
else
echo "entered else portion... are you stuck?"
# btctlout="$(echo "$sinkname/$sinkMAC was already connected."; bluetoothctl list; bluetoothctl info "$sinkMAC")"
btctlout=( "$sinkname1/$sinkMAC was already connected." "$(bluetoothctl list)" "$(bluetoothctl info $sinkMAC)" )
printf %s\\n "${btctlout[@]}"
fi
printf '%scheck/start autossh%s\n\n' "$bold" "$tput0"
startautosshout=( "$(startautossh&)" )
#pause "$(printf '%srestarting ffplay screen%s\n\n' "$bold" "$tput0")"
#pause "${bold}restarting ffplay screen$tput0"
stopffplay
if "$verbose"; then
screenout=$(screen -ls)
printf '\n%s%sNo mpd.zmq screens should be open:%s \n%s%s' "$yellow" "$bold" "$tput0" "$(hr)" "$screenout"
fi
#fg >/dev/null
startffplayout=( "$(startffplay&)" )
zmqoutput="$(mpcp outputs|\grep ffmpeg\/zmq|awk '{print $2}')"
enableout=$(mpcp enable "$zmqoutput")
playout=$(mpctitle play)
pulsemixer --unmute
wait #for the output of startautossh() & startffplay() and then display it.
if "${verbose:-false}"; then printf '%s\n\n%s' "${startautosshout[@]}" "${startffplayout}"; fi
# Start a new detached screen session named "mpd.zmq" running ffplay
# screen -dmS mpd.zmq ffplay -nodisp zmq:tcp://localhost:5555 -loglevel debug
if "$verbose"; then
printf '\n%s%sAn autossh/ssh should be running a tunnel to %s on %s which ffplay is using:%s \n' \
"${yellow}" \
"${bold}" \
"$mpdhost" \
"$tunport" \
"$tput0"
hr
mpdhost1="[${mpdhost:0:1}]${mpdhost:1}"
ps aux|grep --color=never "[${tunport:0:1}]${tunport:1}"|grep --color=always -E autossh\|ffplay\|"$mpdhost" ||
ps aux|grep --color=always [a]utossh
\sleep 1.25s
printf '\n%s%sProcess pid info:%s\n' "$bold" "$yellow" "$tput0"
hr
printf %s\ %s\\n "$autosshpid" "$(cat "$autosshpid")"
\sleep 1.25s
printf %s\ %s\\n "$ffplaypid" "$(cat "$ffplaypid")"
# [[ "$connected" = no ]] && btctlout="$btctlout $({ bluetoothctl list; bluetoothctl info; }|grep -E 'Controller|Device|Name:|Paired:|Connected:')"
# btctlout="$btctlout $(echo; bluetoothctl info)"
printf \\n%s%sBluetooth\ device%s\ %s%s\/%s%s\:%s\\n \
"$bold" \
"$yellow" \
"$tput0" \
"$blue" \
"$sinkname" \
"$sinkMAC" \
"$yellow" \
"$tput0"
hr
####
printf %s\\n "${btctlout[@]}"|grep --color=always -Ei 'Controller|Attempting|Connection|not\ available|"$sincMAC"|Device|Name:|Paired:|Connected:'
####
\sleep 1s
printf '\n%s%sMPD enable fmpeg/zmq output:%s\n' "$bold" "$yellow" "$tput0"
hr
printf %s\\n "$(echo "$enableout"|grep --color=always ffmpeg\/zmq)"
\sleep 1s
printf '\n%s%sPlay mpd: %s' "$bold" "$yellow" "$tput0"
printf %s\\n\\n "$playout"
fi
rm -rf "$tmpdir"
exit