You are not logged in.

#1 2008-09-10 19:14:03

fflarex
Member
Registered: 2007-09-15
Posts: 466

[SOLVED] script to shutdown after the current mpd song is over

So I'm trying to write a script to halt my computer after the currently playing song is finished, as it's something I've been doing manually a lot. Problem is, I can't get it to work. Here's what I have so far:

#!/bin/bash

TMP_FILE="$HOME/bin/tmp/.mpd_end.tmp"
CMD="echo This is where the computer would halt."

# if the command is interupted, make sure $TMP_FILE isn't left behind
trap "rm $TMP_FILE; exit" SIGHUP SIGINT SIGTERM

# mpc should output 3 lines if a song is playing, but only 1 if it isn't
mpc > $TMP_FILE

# check to see if a song is playing by examining the line count of $TMP_FILE
# if there is one playing, get rid of extraneous lines in $TMP_FILE, otherwise exit with an error
if [ `wc -l $TMP_FILE` = "3" ]; then
    head -n 1 $TMP_FILE > $TMP_FILE
else
    echo "Error: no song is currently playing."
    rm $TMP_FILE
    exit 1
fi

# check every 2 seconds to see if the song is over, then move on
# currently the script doesn't even make it this far
while [ `mpc | head -n 1` = `cat $TMP_FILE` ]; do
    sleep 2
done

rm $TMP_FILE
exec $CMD

I have no idea what is wrong with the code, but the errors I get are because $TMP_FILE never actually gets written for some reason. Any help?

EDIT: Oh, and I apologize for the lack of comments. I'll add those in a little bit, but I don't think it's that hard to understand, as long as you know that mpc will output 3 lines if a song is playing and only 1 line if it isn't.

EDIT: Comments added.

Last edited by fflarex (2008-09-12 12:16:16)

Offline

#2 2008-09-10 19:45:48

Arkane
Member
From: Switzerland
Registered: 2008-02-18
Posts: 263

Re: [SOLVED] script to shutdown after the current mpd song is over

Seems

wc -l <file>

doesn't only print the number of lines in the file, but the file's name as well:

quentin@q-eee> mpc > test
quentin@q-eee> wc -l test
3 test

in which case your if condition will never be true.

Last edited by Arkane (2008-09-10 19:47:08)


What does not kill you will hurt a lot.

Offline

#3 2008-09-10 19:58:42

Daenyth
Forum Fellow
From: Boston, MA
Registered: 2008-02-24
Posts: 1,244

Re: [SOLVED] script to shutdown after the current mpd song is over

You can't open a file for reading and writing in the same line.

head -n 1 $TMP_FILE > $TMPFILE # Don't do this
sed -i '1!d' $TMP_FILE # Do this instead

Better yet, use another method.

mpc | awk '$NR == 2 && /^[playing]/ { print "playing" } > $TMP_FILE

Last edited by Daenyth (2008-09-10 20:00:21)

Offline

#4 2008-09-10 22:47:44

Arkane
Member
From: Switzerland
Registered: 2008-02-18
Posts: 263

Re: [SOLVED] script to shutdown after the current mpd song is over

You sure it really does? ~/bin/tmp makes for a real weird director layout...

Last edited by Arkane (2008-09-10 22:48:06)


What does not kill you will hurt a lot.

Offline

#5 2008-09-11 17:52:00

Daenyth
Forum Fellow
From: Boston, MA
Registered: 2008-02-24
Posts: 1,244

Re: [SOLVED] script to shutdown after the current mpd song is over

Try putting "set -x" at the top of the script, and "set +x" at the bottom, then run it again. It might help you figure it out.

Offline

#6 2008-09-11 21:43:40

gnud
Member
Registered: 2005-11-27
Posts: 181

Re: [SOLVED] script to shutdown after the current mpd song is over

The solution follows: Requirements: Perl and mpc

#!/usr/bin/perl

$action = shift;
$song = `mpc|head -n1`;

do {
    sleep(2);
    $newsong = `mpc|head -n1`;
} while($song eq $newsong);

print "Song changed!\n";
print "Taking action: '$action'\n\n";
exec($action);

Name it something appropriate (mine is ~/bin/mpd-on-change) and call it (like mpd-on-change "sudo halt").

Should be easy to modify for playing/stopped status as well. (EDIT: actually, it works if MPD stops, because the first line of mpc output is different.)

Good luck smile

Last edited by gnud (2008-09-11 21:45:54)

Offline

#7 2008-10-20 16:09:46

gnud
Member
Registered: 2005-11-27
Posts: 181

Re: [SOLVED] script to shutdown after the current mpd song is over

Just for anybody who searched for this problem and ended up here:
This is some updated code by fflarex, which he posted in another thread -- same idea as mine above, but in bash, and with additional features.

#!/bin/bash
# 
# ~/bin/mpd-on-change - Waits for MPD's status to change (usually the end of a
#                       song), and optionally executes an action afterwards.

# Print a help message
function usage {
    echo "
mpd-on-change  -  Waits for MPD's status to change (usually the end of a song),
                  and optionally executes an action afterwards.

Usage: mpd-on-change [[-i | --interval] seconds] [[-n | --songs] songs] \\
                     [[-a | --action] command.. ]

Options:
  -a, --action    Execute some action after song(s) finish. Anything after this
                  option is taken to be a command.
  -i, --interval  Set the time between checking the current song. May be in any
                  format supported by sleep. Default is 2.
  -n, --songs     Set the number of songs to wait for. Default is 1.
  -h, --help      Display this help message and exit.

Note  that stopping a song, or starting one when MPD is stopped,  will signal a
change as if the song had finished.  This script requires that mpc be installed
and MPD be running.
"
}

# What to do in case of incorrect usage
function error_exit {
    usage
    exit 1
}

# Makes sure mpc is installed and mpd is running
if [ `mpc | wc -l` -eq 0 ]; then
    error_exit
fi

# $number is the number of songs to complete before finishing up
# $interval is the length of time between checking the current song
# $action is what is executed after the songs play

number=1
interval=2
action=:

# Detect command line arguments
while [ "$1" != "" ]; do
    case $1 in
        -a | --action )     shift
                            action=$*
                            break
                            ;;
        -i | --interval )   shift
                            interval=$1
                            ;;
        -n | --songs )      shift
                            number=$1
                            ;;
        -h | --help )       usage
                            exit
                            ;;
        * )                 error_exit
    esac
    shift
done

# Tests that $number is a non-negative integer
test $number -ge -1 2> /dev/null || error_exit

# Tests to see if $interval is valid input for sleep
# Note that this adds an extra sleep command, which usually won't matter
sleep $interval 2> /dev/null || error_exit


# $song keeps track of which song needs to finish
# $cur_song is the currently playing song

song=`mpc | head -n 1`
cur_song=$song

# $count keeps track of how many songs have finished playing
# This is the meat of the program, which periodically checks the current song
count=0
until [ $count -eq $number ]; do
    while [ "$cur_song" = "$song" ]; do
        sleep $interval
        cur_song=`mpc | head -n 1`
    done
    count=$((count + 1))
    song=`mpc | head -n 1`
done

# Action to be executed at the end, default does nothing
$action

Offline

#8 2009-01-30 22:27:49

markp1989
Member
Registered: 2008-10-05
Posts: 431

Re: [SOLVED] script to shutdown after the current mpd song is over

gnud wrote:

Just for anybody who searched for this problem and ended up here:
This is some updated code by fflarex, which he posted in another thread -- same idea as mine above, but in bash, and with additional features.

#!/bin/bash
# 
# ~/bin/mpd-on-change - Waits for MPD's status to change (usually the end of a
#                       song), and optionally executes an action afterwards.

# Print a help message
function usage {
    echo "
mpd-on-change  -  Waits for MPD's status to change (usually the end of a song),
                  and optionally executes an action afterwards.

Usage: mpd-on-change [[-i | --interval] seconds] [[-n | --songs] songs] \\
                     [[-a | --action] command.. ]

Options:
  -a, --action    Execute some action after song(s) finish. Anything after this
                  option is taken to be a command.
  -i, --interval  Set the time between checking the current song. May be in any
                  format supported by sleep. Default is 2.
  -n, --songs     Set the number of songs to wait for. Default is 1.
  -h, --help      Display this help message and exit.

Note  that stopping a song, or starting one when MPD is stopped,  will signal a
change as if the song had finished.  This script requires that mpc be installed
and MPD be running.
"
}

# What to do in case of incorrect usage
function error_exit {
    usage
    exit 1
}

# Makes sure mpc is installed and mpd is running
if [ `mpc | wc -l` -eq 0 ]; then
    error_exit
fi

# $number is the number of songs to complete before finishing up
# $interval is the length of time between checking the current song
# $action is what is executed after the songs play

number=1
interval=2
action=:

# Detect command line arguments
while [ "$1" != "" ]; do
    case $1 in
        -a | --action )     shift
                            action=$*
                            break
                            ;;
        -i | --interval )   shift
                            interval=$1
                            ;;
        -n | --songs )      shift
                            number=$1
                            ;;
        -h | --help )       usage
                            exit
                            ;;
        * )                 error_exit
    esac
    shift
done

# Tests that $number is a non-negative integer
test $number -ge -1 2> /dev/null || error_exit

# Tests to see if $interval is valid input for sleep
# Note that this adds an extra sleep command, which usually won't matter
sleep $interval 2> /dev/null || error_exit


# $song keeps track of which song needs to finish
# $cur_song is the currently playing song

song=`mpc | head -n 1`
cur_song=$song

# $count keeps track of how many songs have finished playing
# This is the meat of the program, which periodically checks the current song
count=0
until [ $count -eq $number ]; do
    while [ "$cur_song" = "$song" ]; do
        sleep $interval
        cur_song=`mpc | head -n 1`
    done
    count=$((count + 1))
    song=`mpc | head -n 1`
done

# Action to be executed at the end, default does nothing
$action

how can i have this so it runs contently, and runs teh command on each song change?


Desktop: E8400@4ghz - DFI Lanparty JR P45-T2RS - 4gb ddr2 800 - 30gb OCZ Vertex - Geforce 8800 GTS - 2*19" LCD
Server/Media Zotac GeForce 9300-ITX I-E - E5200 - 4gb Ram - 2* ecogreen F2 1.5tb - 1* wd green 500gb - PicoPSU 150xt - rtorrent - xbmc - ipazzport remote - 42" LCD

Offline

#9 2009-02-03 02:39:57

fflarex
Member
Registered: 2007-09-15
Posts: 466

Re: [SOLVED] script to shutdown after the current mpd song is over

markp1989 wrote:

how can i have this so it runs contently, and runs teh command on each song change?

Here's an updated version of the script which can do this with the new -r switch. It also runs on all POSIX-compliant shells now, instead of just bash (so you can, for example, change the first line to '#!/bin/dash' if you want faster performance).

#!/bin/sh
# 
# ~/bin/mpd-on-change - Waits for MPD's status to change (usually at the end of
#                       a song), and optionally executes an action afterwards.

# TODO:
# recognize song changes when the title and artist are identical
# maybe add some kind of timeout or something (for when $nsongs is larger than
#   the number of remaining songs in the playlist, a song is paused for way too
#   long, or similar situations)

# Print a help message
usage() {
    echo "
mpd-on-change  -  Waits for MPD's status to change (usually the end of a song),
                  and optionally executes an action afterwards.

Usage: mpd-on-change [[-i | --interval] time] [[-n | --songs] songs] \
                     [-r | --respawn] [[-a | --action] command.. ]

Options:
  -a, --action    Execute some action after song(s) finish. Anything after this
                  option is taken to be a command.
  -i, --interval  Set the time between checking the current song. May be in any
                  format supported by sleep. Default is 2.
  -n, --songs     Set the number of songs to wait for. Default is 1.
  -r, --respawn   Respawn the script after exiting.
  -h, --help      Display this help message and exit.

Note  that stopping a song, or starting one when MPD is stopped,  will signal a
change as if the song had finished.  It also does not  register song changes if
the title and artist of the songs are identical.  This script requires that mpc
be installed and MPD be running.
"
}

# What to do in case of incorrect usage
error_exit() {
    usage
    exit 1
}

# Makes sure mpc is installed and mpd is running
if [ `mpc | wc -l` -eq 0 ]; then
    error_exit
fi

# $action is what is executed after the songs play
# $interval is the length of time between checking the current song
# $nsongs is the number of songs to complete before finishing up
# $respawn is whether or not to respawn after exiting

action=:
interval=2
nsongs=1
respawn=false

# Detect command line arguments
while [ "$1" != "" ]; do
    case $1 in
        -a | --action )     shift
                            action="$@"
                            break
                            ;;
        -i | --interval )   shift
                            interval=$1
                            ;;
        -n | --songs )      shift
                            nsongs=$1
                            ;;
        -r | --respawn )    respawn=true
                            ;;
        -h | --help )       usage
                            exit
                            ;;
        * )                 error_exit
    esac
    shift
done

# Tests that $nsongs is a non-negative integer
test $nsongs -ge -1 2> /dev/null || error_exit

# Tests to see if $interval is valid input for sleep
# Note that this adds an extra sleep command, which usually won't matter
sleep $interval 2> /dev/null || error_exit


# $song keeps track of which song needs to finish
# $cur_song is the currently playing song

song=`mpc | head -n 1`
cur_song=$song

# $count keeps track of how many songs have finished playing
# This is the meat of the script, which periodically checks the current song
count=0
until [ $count -eq $nsongs ]; do
    while [ "$cur_song" = "$song" ]; do
        sleep $interval
        cur_song=`mpc | head -n 1`
    done
    count=$(($count + 1))
    song=`mpc | head -n 1`
done

# Action to be executed at the end, default does nothing
$action

# Respawn if the -r command line switch was used
if `$respawn`; then
    exec mpd-on-change --interval $interval --songs $nsongs \
                       --respawn --action $action
fi

EDIT: Please see the new and improved mpd-wait, the direct successor to this script.

Last edited by fflarex (2009-08-23 01:43:30)

Offline

Board footer

Powered by FluxBB