Home of the Squeezebox™ & Transporter® network music players.
Page 3 of 3 FirstFirst 123
Results 21 to 29 of 29
  1. #21
    Thanks Paul, this stuff seems to be real "hard core"

  2. #22
    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
    Working fine, but polling uses >10% more CPU and energy and gives a little delay. Suggestion:

    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

  3. #23
    Junior Member
    Join Date
    Jul 2020
    Posts
    29
    Quote Originally Posted by Greg Erskine View Post
    hi sakos,

    Generally speaking the "pcp commands" are only a simple interface into LMS commands. They can only respond as LMS responds.

    Having said that, reading the documentation we should get an "undefined" value. Maybe we have coded a default value of stop.

    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>"
    I have added your post to the list of things todo.

    regards
    Greg
    Where can I find this code in Github? Maybe I can do this small change myself.

  4. #24
    Senior Member Greg Erskine's Avatar
    Join Date
    Sep 2006
    Location
    Sydney, Australia
    Posts
    1,917
    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

  5. #25
    Junior Member
    Join Date
    Jul 2020
    Posts
    29
    Quote Originally Posted by Greg Erskine View Post
    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
    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?

  6. #26
    Senior Member Greg Erskine's Avatar
    Join Date
    Sep 2006
    Location
    Sydney, Australia
    Posts
    1,917
    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>"
    So the pcp_lms_mode function handles the "play", "stop" or "pause" responses. It should have extra code to check for undefined and return "off".

  7. #27
    "play"
    "stop"
    "pause"
    "off"
    "unknown" - no connect to LMS

    ?

    Aki

  8. #28
    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

  9. #29
    Junior Member
    Join Date
    Jul 2020
    Posts
    29
    Quote Originally Posted by Greg Erskine View Post
    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>"
    So the pcp_lms_mode function handles the "play", "stop" or "pause" responses. It should have extra code to check for undefined and return "off".
    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.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •