« PHP – decoding ‘gzinflate(str_rot13(base64_decode’ hack attempts | Main | Reading DS18B20 Temperature sensors with DigiTemp »
Fedora Linux – using Sound via Cron
By Dale Reagan | April 17, 2012
As a ‘logged in user’, playing a sound file (i.e. *.WAV or other audio file format) is really quite simple on Linux systems – you need:
- hardware that can generate sound output,
- one or more speakers connected to output ports, and
- software to read/render the auditory data.
I have been using Fedora for several years (the foundation for the commercial version of Red Hat Linux). Note that sound-related tools/programs for Linux versions are usually available across most flavors of Linux. Most of these tools ‘work the same’ and usually have the same ‘foundation’ requirements (some suite of sound-related programs & libraries along with supported sound-file formats.) Note that the solution found here may not work/be appropriate for other flavors of Linux…
In this particular case I wanted/needed an automated ‘audio alarm’ for:
- when things go bad OR
- simply don’t work
- just for kicks (i.e. announcing some special event/time.)
With Linux, you can accomplish the above types of tasks using custom ‘alarm’ programs OR using a simple ‘crontab’. In this case I want to use ‘cron’ so I start with some testing (which does not work); this is followed by too much time doing on-line searches but it does provide a couple of solutions.
Current versions of Linux have a dependency between user accounts and hardware access. This creates a situation where the OS cannot utilize all system resources unless you re-configure the OS, use ‘some tricks’ or ‘fake user access’. Linux Audio tools/players used for this test include:
- aplay – Alsa sound player
- mplayer – video & sound player
- play – Sox sound player
- paplay – Pulse audio sound player
At the operating system level, (OS) the ‘sound system’ is Pulse Audio.
Aplay will present a good bit of hardware/OS information which may be helpful in resolving sound generation issues:
$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: SB [HDA ATI SB], device 0: ALC1200 Analog [ALC1200 Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 0: SB [HDA ATI SB], device 1: ALC1200 Digital [ALC1200 Digital] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: HDMI [HDA ATI HDMI], device 3: ATI HDMI [ATI HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: HDMI_1 [HDA ATI HDMI], device 3: ATI HDMI [ATI HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0
and
$ aplay -L default Default front:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog Front speakers surround40:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog 4.0 Surround output to Front and Rear speakers surround41:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog 4.1 Surround output to Front, Rear and Subwoofer speakers surround50:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog 5.0 Surround output to Front, Center and Rear speakers surround51:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog 5.1 Surround output to Front, Center, Rear and Subwoofer speakers surround71:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Analog 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers iec958:CARD=SB,DEV=0 HDA ATI SB, ALC1200 Digital IEC958 (S/PDIF) Digital Audio Output hdmi:CARD=HDMI HDA ATI HDMI, ATI HDMI HDMI Audio Output hdmi:CARD=HDMI_1 HDA ATI HDMI, ATI HDMI HDMI Audio Output
After reviewing the current documentation for aplay and PulseAudio I did not locate an answer to this particular problem (playing sound files from system-level-user crontabs…)
I did locate some Internet discussions which pointed me in a direction for a solution. Best I can tell, for sound to ‘work’ on a current Linux (Fedora) system, a user must be logged into a Gui (windowed) environment. This is really a quite complex, inter-connected environment but it boils down to:
- user must be logged in
- sound is ‘connected’ to the user’s windowed Gui environment
- sound cannot be generated outside of this environment (i.e. at the OS/system level without creating a quasi-Gui environment or attaching to such an environment.)
Some Automated Sound Examples using Cron
Staring with simple cron test:
- a normal user (non-system user) is ‘logged in’ to a Gui environment
- this crontab will ‘play’ once every minute
* * * * * /usr/bin/aplay -q /some_path/sparcle.wav
If you try the above using a ‘system’ account OR using some user account that is NOT logged in then you will most likely get an error like (cron should send an email to the user account):
Subject: Cron <root@your-system>
/usr/bin/aplay -q /some_path/sparcle.wav ALSA lib pulse.c:229:(pulse_connect) PulseAudio: Unable to connect: Connection refused aplay: main:654: audio open error: Connection refused
The error message is actually a ‘general’ message which I could not track down via Internet searching. The indications (guesses on my part) are:
- the audio system is tied to networking
- some sort of security mechanism may be involved.
One suggested work around using the ‘root’ system account – ‘tell’ the sound program which environment to use (which user process tree that it should attach to) – the first example yields the same error as the previous attempt (Unable to connect) but the second wraps the entire command such that the system treats the request as originating from the logged in user; based on testing, the requirement seems to be that you must use an account of a ‘currently logged in user’ in order to generate/play sound files:
* * * * * env DISPLAY=:0.0 /usr/bin/aplay -q /some_path/sparcle.wav
The command below ‘works’ (on my system):
* * * * * env DISPLAY=:0.0 su -c "/some_path/sparcle.wav" Some_USER
If you don’t specify the DISPLAY environment – it still works (on my system…) Note that this crontab will ‘run’ once every minute…
* * * * * su -c "/some_path/sparcle.wav" Some_USER
Testing Sounds from the Linux Console
You should be able to confirm that sound does or does NOT work from a console session by switching to one and trying some sound commands, i.e. while logged into a Gui:
- CTRL+ALT+F2 ## switch to Console TTY #2
- login
- try a sound command (I get errors…)
- CTRL+ALT+F7 ## return to Gui
So, after installing/compiling/testing a number of sound tools/players I could not find one that would work from a non-Gui terminal session — until I noticed a ‘new’ tool (paplay) when I located via apropos (your system may show vastly different results…)
$ apropos sound SoX [sox] (1) - Sound eXchange, the Swiss Army knife of audio manipulation SoX [soxformat] (7) - Sound eXchange, the Swiss Army knife of audio manipulation SoXI [soxi] (1) - Sound eXchange Information, display sound file metadata Text::Soundex (3pm) - Implementation of the soundex algorithm alsactl (1) - advanced controls for ALSA soundcard driver alsamixer (1) - soundcard mixer for ALSA soundcard driver, with ncurses interface alsaunmute (1) - a simple script to initialize ALSA sound devices amixer (1) - command-line mixer for ALSA soundcard driver aplay (1) - command-line sound recorder and player for ALSA soundcard driver arecord [aplay] (1) - command-line sound recorder and player for ALSA soundcard driver default.pa [default] (5) - PulseAudio Sound Server Startup Script icedax (1) - a sampling utility that dumps CD audio data into wav sound files jackd (1) - JACK Audio Connection Kit sound server pabrowse (1) - List PulseAudio sound servers on the network pacat (1) - Play back or record raw or encoded audio streams on a PulseAudio sound server pacmd (1) - Reconfigure a PulseAudio sound server during runtime pactl (1) - Control a running PulseAudio sound server paplay (1) - Play back audio files on a PulseAudio sound server pitchplay (1) - wrapper script to play audio tracks with cdda2wav with different pitches through a soundcard (cdda2wav must have soundcard support enabled) pulseaudio (1) - The PulseAudio Sound System register_sound_dsp (9) - register a DSP device register_sound_midi (9) - register a midi device register_sound_mixer (9) - register a mixer device register_sound_special_device (9) - register a special sound node snd_card_create (9) - create and initialize a soundcard structure snd_card_register (9) - register the soundcard unregister_sound_dsp (9) - unregister a DSP device unregister_sound_midi (9) - unregister a midi device unregister_sound_mixer (9) - unregister a mixer unregister_sound_special (9) - unregister a special sound device
There are 500+ reasons for ‘missing it’ during previous searches… Plus!, ‘paplay’ did not show up in any Internet searches (it should now, though…)
$ apropos play|wc 514
Playing Sound Files in Linux Cron – Conclusion (not!)
Strangely, when I exit the Gui and try using sound players from a system console (TTY0 – aplay, mplayer, paplay) all work for my primary user account as well as for ‘root’… [And I note here, that aplay, play, and mplayer all failed previously… the connection seems to be that I ‘ran’ ‘paplay’ in some manner that ‘set things up’???]
- First confirm that your system can produce sound-file output (i.e. from your Gui.)
- Locate existing ‘sound player’ tools on your system
- In a crontab, you should be able to use the ‘su -c’ option for most players – but note that the USER will most likely need to have an active Gui session…
- If you are using PulseAudio then ‘paplay’ may work for any crontab process.
- The actual ‘best’ process to establish ‘permission to use sound devices’ is described below.
If paplay is not on your Fedora/Red Hat system you can locate the correct package to install via:
$ yum provides “*/paplay”
Loaded plugins: presto, refresh-packagekit, security
pulseaudio-utils-0.9.21-6.fc13.i686 : PulseAudio sound server utilities
Repo : fedora
Matched from:
Filename : /usr/bin/paplay
Once located, it could be installed with:
$ [sudo] yum install pulseaudio-utils # Or
$ [sudo] yum install pulseaudio-utils-0.9.21-6.fc13.i686
Understanding Pulse Audio (from the docs)
http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/PerfectSetup
There are three kind[s] of distributions [Linux versions and how they ‘manage’ sound device hardware access]:
- those who control access to the sound card by adding users to the “audio” group,
- those who use udev (or HAL) and ConsoleKit to dynamically give access to the currently “active” user, but allow overriding that using the “audio” group and
- those who don’t use the “audio” group at all, but rely solely on HAL+ConsoleKit to grant access to the sound card.
To find out which group your distribution belongs to, run ls -l /dev/snd. If the permission field of many of the listed files contains a plus character in the end, like this:
$ ls -l /dev/snd/pcmC0D0p crw-rw----+ 1 root audio 116, 6 Apr 17 16:37 /dev/snd/pcmC0D0p
then your distribution most likely belongs to group 2 or 3. If the group of the file is “audio”, as above, then the distribution belongs to group 2 [Ok, for my Fedora system is in ‘group 2’], otherwise it belongs to group 3.
If there was no plus character in the permission fields, like in this example:
crw-rw—- 1 root audio 116, 7 Aug 2 08:57 pcmC0D0p
then your distribution belongs to group 1.
Now that you know how your distribution does access control to the sound card, it’s easy to determine whether you should put users to the “audio” group or not:
- If your distribution belongs to group 1, you must put all users to the “audio” group or otherwise they can’t access the sound card.
- If your distribution belongs to group 2 or 3, you should make sure that no one is in the “audio” group. (If you plan running pulseaudio in the system-wide mode, then the special user “pulse” should still be in the “audio” group in order to have access to the sound card.)
If your distribution belongs to group 1 or 2, fast user switching doesn’t work properly if users are in the “audio” group
Based on the above I should be able to provide sound ‘access’ to any user by adding them to the ‘audio’ group – off for some testing…
When a user successfully uses a sound device with Pulse audio a ‘.pulse’ folder is created in their home directory. To confirm this I created a user, tested sound (which fails), add the user to the ‘audio’ group and test again.
As the ‘root’ user, create the test account and ‘su’ to the new account.
# [sudo] adduser -m -c "Sound Test - remove when done" soundtester
# [sudo] su - soundtester
Now we try a sound file and get an error.
[soundtester@localhost ~]$ play /tmp/cow play FAIL formats: can't open input file `/tmp/cow': No such file or directory ## check for any new files on the home folder ## [soundtester@localhost ~]$ ls -ltr total 36 -rw-r--r-- 1 soundtester soundtester 500 Jan 23 2007 .emacs drwxr-xr-x 2 soundtester soundtester 4096 Mar 31 2010 .gnome2 -rw-r--r-- 1 soundtester soundtester 124 May 21 2010 .bashrc -rw-r--r-- 1 soundtester soundtester 176 May 21 2010 .bash_profile -rw-r--r-- 1 soundtester soundtester 18 May 21 2010 .bash_logout drwxr-xr-x 4 soundtester soundtester 4096 Jul 24 2010 .mozilla -rw-r--r-- 1 soundtester soundtester 658 May 30 2011 .zshrc
Ok, no new files – next we try ‘paplay’…
[soundtester@localhost ~]$ paplay /tmp/cow.wav No protocol specified XOpenDisplay() failed Connection failure: Connection refused
Ok, not working yet – check home folder and we find some new Files/.pulse folder…
[soundtester@localhost ~]$ ls -ltr
total 44
-rw-r–r– 1 soundtester soundtester 500 Jan 23 2007 .emacs
drwxr-xr-x 2 soundtester soundtester 4096 Mar 31 2010 .gnome2
-rw-r–r– 1 soundtester soundtester 124 May 21 2010 .bashrc
-rw-r–r– 1 soundtester soundtester 176 May 21 2010 .bash_profile
-rw-r–r– 1 soundtester soundtester 18 May 21 2010 .bash_logout
drwxr-xr-x 4 soundtester soundtester 4096 Jul 24 2010 .mozilla
-rw-r–r– 1 soundtester soundtester 658 May 30 2011 .zshrc
-rw——- 1 soundtester soundtester 256 Apr 17 17:06 .pulse-cookie
drwx—— 2 soundtester soundtester 4096 Apr 17 17:06 .pulse
Change to the new folder and list files, (cd /home/soundtester/.pulse).
[soundtester@localhost .pulse]$ l total 12 -rw-r--r-- 1 soundtester soundtester 696 Apr 17 17:06 f77826521fd4c921ab2dcd4d0000001b-card-database.tdb -rw-r--r-- 1 soundtester soundtester 696 Apr 17 17:06 f77826521fd4c921ab2dcd4d0000001b-device-volumes.tdb lrwxrwxrwx 1 soundtester soundtester 23 Apr 17 17:06 f77826521fd4c921ab2dcd4d0000001b-runtime -> /tmp/pulse-CcctT9RwKSB1 -rw-r--r-- 1 soundtester soundtester 696 Apr 17 17:06 f77826521fd4c921ab2dcd4d0000001b-stream-volumes.tdb
Next we add the test user to the ‘audio’ group and retest..
# [sudo] usermod -G audio -a soundtester # [sudo] su - soundtester
$ aplay /tmp/cow.wav ## we get the output below AND the cow MOOOOOOSSSZZZ. No protocol specified XOpenDisplay() failed Playing WAVE '/tmp/cow.wav' : Signed 16 bit Little Endian, Rate 11025 Hz, Mono
Success!
Create a Cron User with Sound Player Access
- [sudo] adduser -m -p soundtest2012 -c “Cron Sound Test” -G audio cronaudiotest
- [sudo] crontab -u cronaudiotest -e
Check that the new user is a member of the ‘audio’ group:
- cat /etc/group | grep cron ## Is the cronaudiotest user present?
Create a new cron to test sound for the test user:
- [root@localhost ~]# crontab -u cronaudiotest -e
### test alarm every XX minutes
*/5 * * * * /usr/bin/paplay /tmp/cow.wav
Don’t forget to turn off the Cow!
Thoughtful/helpful feedback/suggestions are always welcome – know of another/better solution – leave a comment.
As always, your mileage should vary (at least a bit), especially when you factor in all the flavors/versions of Linux. 🙂
Topics: Computer Technology, Problem Solving, System and Network Security, Unix-Linux-Os | Comments Off on Fedora Linux – using Sound via Cron
Comments are closed.