Thanks Paul, this stuff seems to be real "hard core"![]()
Results 21 to 30 of 30
-
2020-09-04, 11:44 #21
- Join Date
- Dec 2017
- Posts
- 57
-
2020-09-06, 14:12 #22
- Join Date
- Dec 2017
- Posts
- 57
Ok, Vers. 0.2 after some polishing:
Code:#!/bin/sh # -------------------------------------------------------------------------------------------------------------------------- # Script polls "pcp mode" every 500 ms and sets a GPIO when squeezelite is playing. # Aki 9/2020 - Home: https://forums.slimdevices.com/showthread.php?110277-Feature-request-picoreplayer-Play-state-to-GPIO # -------------------------------------------------------------------------------------------------------------------------- # Vers 0.2: Cleanup of GPIO on exit. Reentrance cleared. -k kills running instance. Clean reaction on 'pcp mode' outages. BASE_GPIO_PATH=/sys/class/gpio ScriptName=$(basename -- "$0") #Parameters=$@ function msg () { echo "$(date +"%T") $ScriptName: $@"; } # function msg function err () { echo "$(date +"%T") $ScriptName: Error: $1" >&2; exit 1 } # function err function cleanup () { if [ -e $BASE_GPIO_PATH/gpio$myGPIO ]; then # GPIO initialized echo "$((!$PlayVal))" > $BASE_GPIO_PATH/gpio$myGPIO/value # Set to off state echo "$myGPIO" > $BASE_GPIO_PATH/unexport fi # GPIO de-initialized exit 0 } # on Exit function Usage () { echo "" echo "PlayMode to GPIO ($ScriptName) sets a GPIO when squeezelite is playing." echo "--------------------------------------------------------------------" echo "Usage: sudo $0 -g GPIO [-s n] [-f] [-v] [-b] [-k] [-h]" echo "" echo "-g : GPIO-number" echo "-s : Set value for \"play\" mode: 0,1. Default=1 sets GPIO to 3V when playing" echo "-v : Verbose output from background" echo "-f : run in foreground with verbose output" echo "-b : Blink mode, GPIO is blinking when playing" echo "-k : Kill running $ScriptName" echo "-h : Shows this help" echo "" echo "Examples:" echo "---------" echo " sudo $0 -g 27 : Sets GPIO27 to 3V when playing" echo " sudo $0 -g 4 -s 0 -f : Sets GPIO4 to 0V when playing, running in foreground" echo " sudo $0 -g 4 -s 1 -v : Sets GPIO4 to 3V when playing, running in background with output" echo " sudo $0 -g27 -b : Sets GPIO27 to 3V, blinking when playing" echo " sudo $0 -k : Kills running $ScriptName" echo "" exit 1 } # function Usage function Loop () { trap cleanup INT TERM # cleanup GPIO on exit while true; do MODE=`pcp mode 2> /dev/null` if [ ! "$MODE" ]; then MODE=unknown; fi # no result, wget error if [ "$MODE" = "play" ] && $Blink; then # Blink on play actGPIOval=$(cat $BASE_GPIO_PATH/gpio$myGPIO/value) echo "$((!$actGPIOval))" > $BASE_GPIO_PATH/gpio$myGPIO/value fi # Blink on play if [ ! "$MODE" = "$OldMode" ]; then # MODE change if [ "$MODE" = "play" ] || [ "$MODE" = "pause" ] || [ "$MODE" = "stop" ] || [ "$MODE" = "unknown" ]; then # valid or empty MODE msgtxt="pcp mode is \"$MODE\"." if [ "$MODE" = "play" ]; then GPIOval=$PlayVal; else GPIOval=$((!$PlayVal)); fi # Set GPIO value if [ ! "$GPIOval" = "$oldGPIOval" ]; then msgtxt="Set GPIO$myGPIO to $GPIOval. ${msgtxt}" echo "$GPIOval" > $BASE_GPIO_PATH/gpio$myGPIO/value oldGPIOval=$GPIOval fi # GPIO val change msg $msgtxt else # invalid MODE msg "\"pcp mode\" results to invalid mode \"$MODE\", should be play, pause, stop" fi # valid/invalid MODE OldMode=$MODE fi # MODE change sleep 0.5 done # while true } # function Loop ############ ### Main ### ############ # Parameter # --------- if [ ! $1 ]; then Usage; fi # No Param, please give at least the GPIO # Defaults myGPIO= PlayVal=1 # active high Verbose=false # no output from loop when daemonized foreground=false # no more need to foreground Blink=false # stoy active while getopts g:s:vfbkh opt do case $opt in g ) # Check for valid GPIO if [ "$OPTARG" -ge 2 ] && [ "$OPTARG" -le 27 ] then myGPIO=$OPTARG else err "\"$OPTARG\" is not a valid GPIO, please use 2 .. 27"; fi # Check for valid GPIO ;; s ) # Check parameter for setting GPIO to 0 or 1 when playing if [ $OPTARG ]; then # Set GPIO to 0 or 1 when playing if [ "$OPTARG" -eq 0 ] || [ "$OPTARG" -eq 1 ] then PlayVal=$OPTARG else err "\"$OPTARG\" is not a valid GPIO state, please use 0 or 1"; fi fi # Check parameter for setting GPIO to 0 or 1 when playing ;; v ) Verbose=true;; f ) foreground=true;; b ) Blink=true;; k ) msg "Killing running instance."; killall -15 $ScriptName;; h ) Usage;; [?]) Usage;; esac done if [ ! $myGPIO ]; then err "Mandatory parameter -g \"GPIO\" is missing"; fi # Kill old instance, if exists for pid in $(pidof $ScriptName); do if [ ! $pid = $$ ]; then msg "Killing old instance (pid $pid) of $ScriptName" kill -15 $pid until [ ! -e $BASE_GPIO_PATH/gpio$myGPIO ]; do sleep 0.1 # Give the exit routine some time. on pi 3b+ 0.1s is enough done # Wait for ols exit routine finished fi # old instance found done # Kill old instance # Init # ---- # Wait for squeezelite to come online wt=0 until pids=$(pidof squeezelite squeezelite-dsd); do sleep 1; wt=$(($wt+1)) msg "Waited $wt seconds for for squeezelite ..." if [ "$wt" -ge 60 ]; then err "Waited too long for squeezelite"; fi done # Init GPIO if [ ! -e $BASE_GPIO_PATH/gpio$myGPIO ]; then # Init GPIO msg "Export GPIO$myGPIO to userspace" echo "$myGPIO" > $BASE_GPIO_PATH/export fi # Init GPIO msg "Set GPIO$myGPIO as an output" echo "out" > $BASE_GPIO_PATH/gpio$myGPIO/direction # Start loop # ---------- if $foreground; then # run in foreground: msg "Foreground loop polling, with output. Stop with \"ctrl-c\"." Loop else # daemonize if $Verbose; then msg "Background loop polling with output. Stop with \"sudo $0 -k\" or restart of script." Loop & else # Background loop polling with output msg "Background loop polling. Stop with \"sudo $0 -k\" or restart of script." Loop > /dev/null 2>&1 & fi # Background loop polling fi # Start fore- or background loop polling exit # End of Program
The Squeezelite call of "Power On/Off Script" gets some more states:
Now:
2: Init
1: On
0 :Off
Future:
5: stop
4: play
3: pause
2: init
1: on
0: off
So everyone can build nice status LEDs or switch his perifery to his needs.
By the way: "stop" vs. "off" could get some clarification ;-)
Scripting in unknown terrain is the real adventure game
Have fun
Aki
-
2020-09-10, 12:02 #23
- Join Date
- Jul 2020
- Posts
- 29
-
2020-09-10, 13:25 #24
hi sakos,
99% of piCorePlayer is just shell scripts, so the code is on your SD card.
I'd probably start looking at pcp-lms-functions.
There is the extra complication that pCP uses readonly extensions linked to in RAM.
regards
Greg
-
2020-09-11, 05:30 #25
- Join Date
- Jul 2020
- Posts
- 29
Ok, found the pcp_lms_mode() function, but could not see any mapping.
pcp_lms_mode() {
REQUEST=$(pcp_lms_build_request "$NAME" mode ?)
RESULT=$(pcp_lms_build_result result _mode)
pcp_lms_json_request
pcp_lms_build_result() {
#Should be at least 2 arguments, result is almost always the first.
RLOOP="["
pcp_lms_build_loop $@
REQ="$RLOOP]"
# escape the brackets [ ] for egrep and sed
echo $REQ | sed 's/\[/\\\[/' | sed 's/\]/\\\]/'
}
pcp_lms_build_loop() {
if [ "$1" != "" ]; then
[ "$RLOOP" == '[' ] && RLOOP="$RLOOP"$1"" ||RLOOP="$RLOOP,"$1""
shift
NEXT=$@
[ "$NEXT" != "" ] && pcp_lms_build_loop $NEXT
fi
}
Do I understand well?
-
2020-09-11, 13:59 #26
Yes.
From the LMS CLI help:
Code:<playerid> mode ? The "mode" command allows to query the player state and returns one of "play", "stop" or "pause". If the player is off, "mode ?" returned value is undefined. Example: Request: "04:20:00:12:23:45 mode ?<LF>" Response: "04:20:00:12:23:45 mode stop<LF>"
-
2020-09-12, 03:41 #27
- Join Date
- Dec 2017
- Posts
- 57
"play"
"stop"
"pause"
"off"
"unknown" - no connect to LMS
?
Aki
-
2020-09-14, 14:03 #28
- Join Date
- Dec 2017
- Posts
- 57
Vers 0.3: When no GPIO is given, green onboard LED led0 will be used. So will run now without parameters. No more sudo necessary.
Aki
Code:##!/bin/sh # -------------------------------------------------------------------------------------------------------------------------- # pm2gpio script polls "pcp mode" every 500 ms (1 second on Pi Zero) and sets a GPIO when squeezelite is playing. # Aki 9/2020 - Home: https://forums.slimdevices.com/showthread.php?110277-Feature-request-picoreplayer-Play-state-to-GPIO # -------------------------------------------------------------------------------------------------------------------------- # Vers 0.2: Cleanup of GPIO on exit. Reentrance cleared. -k kills running instance. Clear reaction on 'pcp mode' outages. # Vers 0.3: When no GPIO is given, green onboard LED led0 will be used. So will now run without parameters. No more sudo necessary BASE_GPIO_PATH=/sys/class/gpio ScriptName=$(basename -- "$0") function UpTm () { # Returns UpTime sss.ms set `cat -- /proc/uptime` echo "$1" } # function UpTm function mySudo () { echo $@ | sudo sh } # function mySudo function msg () { echo "$(UpTm) $ScriptName: $@"; #echo "$(date +"%T") $ScriptName: $@"; } # function msg function err () { echo "$(UpTm) $ScriptName: Error: $@" >&2; exit 1 } # function err, not called from loop -therefore no need to cleanup? function cleanup () { if [ $PlayGPIO = "0" ]; then # green onboard led0 mySudo "echo mmc0 >/sys/class/leds/led0/trigger" else # GPIO if [ -e $BASE_GPIO_PATH/gpio$PlayGPIO ]; then # GPIO initialized mySudo "echo $((!$PlayVal)) > $BASE_GPIO_PATH/gpio$PlayGPIO/value" # Set to off state mySudo "echo $PlayGPIO > $BASE_GPIO_PATH/unexport" fi # GPIO de-initialized fi # led0 or GPIO exit 0 } # on Exit function Usage () { echo "" echo "PlayMode to GPIO ($ScriptName) sets a GPIO when squeezelite is playing." echo "--------------------------------------------------------------------" echo "Usage: $0 [-g GPIO] [-s n] [-f] [-v] [-b] [-k] [-h]" echo "" echo "-g : GPIO-number play mode, if not given, green onboard (led0) will be used" echo "-s : GPIO-value for play mode [0,1], if not given [1] will be used" echo "-f : run in foreground with verbose output" echo "-v : verbose output from background" echo "-b : blink mode, GPIO is blinking when playing, on on pause" echo "-k : Kill running $ScriptName" echo "-h : Shows this help" echo "" echo "Examples:" echo "---------" echo " $0 : Green onboard LED (led0) on when playing" echo " $0 -b : Green onboard LED (led0) blinking when playing, on when paused" echo " $0 -g27 : Sets GPIO27 to 3V when playing" echo " $0 -g27 -b : Sets GPIO27 to 3V, blinking when playing, on when pause" echo " $0 -g4 -s0 -f : Sets GPIO4 to 0V when playing, running in foreground with output (debug)" echo " $0 -g4 -s1 -v : Sets GPIO4 to 3V when playing, running in background with output (debug)" echo " $0 -k : Kills running $ScriptName" echo "" exit 1 } # function Usage function Loop () { trap cleanup INT TERM # cleanup GPIO on exit while true; do MODE=`pcp mode 2> /dev/null` if [ ! "$MODE" = "$OldMode" ]; then # MODE change if [ ! "$MODE" ]; then MODE="not available"; fi # no result, wget error msg "pcp mode is \"$MODE\"." if [ "$MODE" = "play" ] || [ "$MODE" = "pause" ] || [ "$MODE" = "stop" ] || [ "$MODE" = "not available" ]; then # valid or empty MODE if [ "$MODE" = "play" ]; then GPIOval=$PlayVal; # on elif $blink && [ "$MODE" = "pause" ]; then GPIOval=$PlayVal # on else GPIOval=$((!$PlayVal)) # off fi else # unknown MODE msg "\"pcp mode\" results to unknown mode \"$MODE\", should be play, pause, stop" fi # valid/invalid MODE OldMode=$MODE fi # MODE change # blink if $blink && [ "$MODE" = "play" ]; then GPIOval="$((!$GPIOval))"; fi # invert, blinking if [ ! "$GPIOval" = "$oldGPIOval" ]; then if ! $blink; then msg "Set GPIO$PlayGPIO to $GPIOval."; fi if [ $PlayGPIO = "0" ]; then # led0 if [ $GPIOval = "1" ]; then mySudo "echo 1 >/sys/class/leds/led0/brightness" else mySudo "echo 0 >/sys/class/leds/led0/brightness" fi else # GPIO mySudo "echo $GPIOval > $BASE_GPIO_PATH/gpio$PlayGPIO/value" fi oldGPIOval=$GPIOval fi # GPIO val change sleep 0.5 done # while true } # function Loop ############ ### Main ### ############ # Parameter # --------- #if [ ! $1 ]; then Usage; fi # No Param, please give at least the GPIO # Defaults PlayGPIO=0 # default green onboard led0 PlayVal=1 # default active high foreground=false # no more need to foreground verbose=false # no output from loop when daemonized blink=false # stay active oldGPIOval=0 while getopts g:s:fvbkh opt do case $opt in g ) # Check for valid Play GPIO if [ "$OPTARG" -ge 2 ] && [ "$OPTARG" -le 27 ] then PlayGPIO=$OPTARG else err "Play GPIO \"$OPTARG\" is not a valid GPIO, please use 2 .. 27"; fi # Check for valid GPIO ;; s ) # Check parameter for setting GPIO to 0 or 1 when playing if [ $OPTARG ]; then # Set GPIO to 0 or 1 when playing if [ "$OPTARG" -eq 0 ] || [ "$OPTARG" -eq 1 ] then PlayVal=$OPTARG else err "Play-value \"$OPTARG\" is not a valid GPIO state, please use 0 or 1"; fi fi # Check parameter for setting GPIO to 0 or 1 when playing ;; f ) foreground=true;; v ) verbose=true;; b ) blink=true;; k ) msg "Killing running instance."; sudo killall -15 $ScriptName;; h ) Usage;; [?]) Usage;; esac done # Kill old instance, if exists for pid in $(pidof $ScriptName); do if [ ! $pid = $$ ]; then msg "Killing old instance (pid $pid) of $ScriptName" mySudo "kill -15 $pid" sleep 0.3 # Give the exit routine some time. on pi 3b+ 0.1s is enough fi # old instance found done # Kill old instance # Init # ---- # Wait for squeezelite to come online wt=0 until pids=$(pidof squeezelite squeezelite-dsd); do sleep 1; wt=$(($wt+1)) msg "Waited $wt seconds for for squeezelite ..." if [ "$wt" -ge 60 ]; then err "Waited too long for squeezelite"; fi done # Init GPIO if [ $PlayGPIO = "0" ]; then # led0 msg "Disable mmc0 trigger on led0" mySudo "echo none >/sys/class/leds/led0/trigger" else # GPIO if [ ! -e $BASE_GPIO_PATH/gpio$PlayGPIO ]; then # Init GPIO msg "Export GPIO$PlayGPIO to userspace" mySudo "echo $PlayGPIO > $BASE_GPIO_PATH/export" fi # Init GPIO msg "Set GPIO$PlayGPIO as an output" mySudo "echo out > $BASE_GPIO_PATH/gpio$PlayGPIO/direction" fi # led0 or GPIO # Call Loop # ---------- if $foreground; then # foreground: msg "Foreground loop polling, with output. Stop with \"ctrl-c\"." Loop else # daemonize if $verbose; then # Background loop polling with output msg "Background loop polling with output. Stop with \"$0 -k\" or restart of script." Loop & else # Background loop polling msg "Background loop polling. Stop with \"sudo $0 -k\" or restart of script." Loop > /dev/null 2>&1 & fi # Background loop polling fi # Start fore- or background loop polling exit # End of Program
-
2020-09-16, 04:34 #29
- Join Date
- Jul 2020
- Posts
- 29
Where is the undefined response mapped to "stop", currently? Because "pcp mode" response is "stop" after "pcp power off" command sent. Maybe LMS response is also "stop" in this case?
Disregard my question. Now GPIO control in case of player power off working fine in squeezlite.Last edited by sakos; 2020-09-17 at 02:38.
-
2021-01-05, 11:03 #30
- Join Date
- Jul 2020
- Posts
- 254
This works great, thanks! I wanted to add a simple play/pause button to some of my players and this is precisely what I needed. Just copy/paste and worked 'out of the box'.
Maybe it should be added to the PcP manual pages?