Register
It is currently Fri Oct 24, 2014 10:15 pm

Do something until I press a key


All times are UTC - 6 hours


Post new topic Reply to topic  [ 6 posts ] 
Author Message
 PostPosted: Sun Aug 30, 2009 4:18 pm   

Joined: Sun Aug 30, 2009 4:11 pm
Posts: 4
Hi to everybody!
I want to repeat an action (playing an audio file) until I press a key on my keyboard.
The latter can be achieved with read -n 1, but how do I insert the whole into a loop that waits for my input and plays in the meanwhile?
I hope I've been clear enough...

Thanks in advance!


Top
 Profile  
 PostPosted: Mon Aug 31, 2009 1:28 am   

Joined: Mon Nov 17, 2008 7:25 am
Posts: 221
Trap might do the trick. But I believe it only handles sig's.
http://linux.die.net/man/1/trap


Another solution could be something like this.
Code:
#!/bin/bash

program_i_want_to_run &
read tmp
pid=$(pidof program_i_want_to_run)
kill $pid


This will run the program, and then wait for your input into read, the $tmp variable is not of any concern since you just want to use read to "pause" the script.
kill $pid will kill all the instances with the same name, so this can be a bit risky if your application is named the same way as something you really want to keep.

Best regards
Fredrik Eriksson


Top
 Profile  
 PostPosted: Mon Aug 31, 2009 3:44 am   

Joined: Sun Aug 30, 2009 4:11 pm
Posts: 4
Thanks for your reply.
Quote:
kill $pid will kill all the instances with the same name, so this can be a bit risky if your application is named the same way as something you really want to keep.

A solution for not killing all the instances with the same name may be to call pidof with -s, that returns only the last one.

Anyway, perhaps I didn't explain very well that I'd like to start looping a ring bell that plays until I press a key. Basically, I would need to break a the execution of a block of code when any input from the keyboard is received. I don't know if it's possible within a bash script...

I took a rapid look to trap, but I could not find it very useful for my purposes. A dirty trick should be:
Code:
echo "Press Ctrl+c to stop playing"
trap "kill $$" SIGINT
while true ; do
    aplay ringbell.wav
    sleep 1
done

This way I would avoid pressing Ctrl+c 2 times, one to kill aplay and one to exit the loop.

Another partial solution is:
Code:
while true ; do
    aplay ringbell.wav
    read -t 1 -n 1 && break
done

It plays the file and then waits for the user input. If no key is pressed within 1 second, sound file is played again, otherwise the loop breaks. The drawback is that I can only stop the loop whithin the short time of a second.

Regards


Top
 Profile  
 PostPosted: Mon Aug 31, 2009 4:28 am   

Joined: Mon Nov 17, 2008 7:25 am
Posts: 221
Well you could always do a little if check.

Code:
while [ true ]; do
   read -t 1 -n 1 tmp_var
   if [ ! -z $tmp_var ]; then
       exit 0
   fi
done


Not sure if this would work, since just pressing enter would make the $tmp_var contain "" which I think is the same as zero valued variable.

Problem with using read is that there is no way of checking if the variable is set in the first place. tmp_var="" is the same as not setting tmp_var, in contrast to other programming languages where setting "" inits the variable.
PHP or perl for example can check if the variable is set by using
PERL: if($var) { }
PHP: if(isset($var)) { }

Even thou both of these languages can declare content in a variable without first typecasting or defining the existance of a variable.

If anyone have a suggestion on how to check for a variables existance I would love to hear it :)

Anyway, back on topic.
script1.sh
Code:
#!/bin/bash
# Create a script to run ringbell.wav until script is killed. Also begin with returning the current PID
echo "
#!/bin/bash
pid=\$\$
echo $pid
while [ true ]; do
   aplay ringbell.wav
   sleep 1
done
" > /tmp/tmp.sh

# Execute and run the created script.
pid=$(bash /tmp/tmp.sh &)
# Wait for read.
read -n 1 -s tmp
# Kill the pid returned.
kill $pid
rm /tmp/tmp.sh


This could probably work as you want, but it's not fool proof... ctrl, alt and special keys that doesn't output a specific character won't be catched.

The best solution might be to either find a perl extension library which is built to handle keypresses or write a program in c or the like which can exit with a return value.

Anyway, going to stop ranting now and get back to work :P

Best regards
Fredrik Eriksson


Top
 Profile  
 PostPosted: Mon Aug 31, 2009 2:46 pm   

Joined: Sun Aug 30, 2009 4:11 pm
Posts: 4
The temp file approach seems the best so far and it was my next option indeed.
Code:
# random seed and string
str=`echo $$ | md5sum | md5sum`
rand_str=${str:2:12}

# create a temp file with an unique name
tmp_file=/tmp/$rand_str

cat << EOQ > $tmp_file
#!/bin/bash
while true ; do
   aplay $sound
   sleep 1
done
EOQ

# Make it executable
chmod a+x $tmp_file

# Play the ring bell by executing the temp file
$tmp_file >/dev/null 2>&1 &

# Wait for a second to get the process id
sleep 1
pid=`ps x | grep $tmp_file | cut -d' ' -f 1`

echo "Press any key to stop playing the ring bell"

# read user input
read -n 1 -s tmp

# Kill the pid returned.
kill $pid >/dev/null

# remove temp file
if [[ -x $tmp_file ]] ; then
   rm -f $tmp_file >/dev/null 2>&1
fi

It's not fool proof too, but it does the trick!
Thanks for your help.


Top
 Profile  
 PostPosted: Tue Sep 01, 2009 6:03 am   
Moderator
User avatar

Joined: Thu Oct 11, 2007 7:12 am
Posts: 229
Location: London - UK
fredrik.eriksson wrote:

If anyone have a suggestion on how to check for a variables existance I would love to hear it :)



this only returns non-empty if myvar is set
Code:
set | egrep '^myvar='


Also the following can be useful, causes bash to error when it tries to expand an unset variable
Code:
set -u


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP