Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set volume using php exec and amixer

I wrote a little php script to control the volume of my local machine with alsa:

<?php
# for simplicity and testing it really just executes the command:
echo exec('amixer set Master 5%+') . " \n";

Now when I run this script on command line it works fine:

$ php volume.php 
Front Right: Playback 39226 [60%] [on] 
$ php volume.php 
Front Right: Playback 42503 [65%] [on] 
$ php volume.php 
Front Right: Playback 45780 [70%] [on]

I have music playing and I hear it getting louder.

But when I try to run the script via apache from the browser calling http://localhost/volume.php it doesn't work.

# http://localhost/volume.php
Front Right: Playback 55709 [10%] [on]
# F5
Front Right: Playback 55709 [15%] [on]
# F5
Front Right: Playback 55709 [20%] [on]

Now I hear no change in volume and the percentages seem to be unrelated to the current state. It says 10% - 15% - 20% when it really is still at 70%.

My apache is running as my user so exec('whoami') gives me the username I am logged in with on my shell where everything works fine.

# httpd.conf
User mkt
Group mkt

I'm on Fedora 22.

Probably it's due to the apache2 process environment. Any ideas how to fix this?

UPDATE:

This is the output of aplay -L:

[mkt@localhost ~]$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
pulse
    PulseAudio Sound Server
default
    Default ALSA Output (currently PulseAudio Sound Server)
sysdefault:CARD=Intel
    HDA Intel, ALC888 Analog
    Default Audio Device
front:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    Front speakers
surround21:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    4.0 Surround output to Front and Rear speakers
surround41:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Intel,DEV=0
    HDA Intel, ALC888 Analog
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
iec958:CARD=Intel,DEV=0
    HDA Intel, ALC888 Digital
    IEC958 (S/PDIF) Digital Audio Output
hdmi:CARD=NVidia,DEV=0
    HDA NVidia, HDMI 0
    HDMI Audio Output
hdmi:CARD=NVidia,DEV=1
    HDA NVidia, HDMI 1
    HDMI Audio Output
hdmi:CARD=NVidia,DEV=2
    HDA NVidia, HDMI 2
    HDMI Audio Output
hdmi:CARD=NVidia,DEV=3
    HDA NVidia, HDMI 3
    HDMI Audio Output

On command line only default and pulse are working:

amixer -D pulse set Master 5%+
amixer -D default set Master 5%+

With PHP even those two don't work. Anyway... my sound comes from my monitors speakers which is plugged in via hdmi. So I guess the last 4 devices are my candidates. But non of them work.

$ amixer -D hdmi:CARD=NVidia,DEV=0 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=1 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=2 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=3 set Master 5%+

In all four cases it says: (with DEV=[0-3] of course)

ALSA lib control.c:954:(snd_ctl_open_noupdate) Invalid CTL hdmi:CARD=NVidia,DEV=3
amixer: Mixer attach hdmi:CARD=NVidia,DEV=3 error: No such file or directory

UPDATE

Output of aplay -l:

$ aplay -l

**** List of Hardware-Devices (PLAYBACK) ****
Card 0: Intel [HDA Intel], Device 0: ALC888 Analog [ALC888 Analog]
  Sub-Devices: 1/1
  Sub-Device #0: subdevice #0
Card 0: Intel [HDA Intel], Device 1: ALC888 Digital [ALC888 Digital]
  Sub-Devices: 1/1
  Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 3: HDMI 0 [HDMI 0]
  Sub-Devices: 1/1
  Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 7: HDMI 1 [HDMI 1]
  Sub-Devices: 0/1
  Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 8: HDMI 2 [HDMI 2]
  Sub-Devices: 1/1
  Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 9: HDMI 3 [HDMI 3]
  Sub-Devices: 1/1
  Sub-Device #0: subdevice #0

$ amixer -c0 set Master 5%+
$ amixer -c1 set Master 5%+

Both don't work!

SOLUTION:

Thanks for all the help! The answer though came from https://superuser.com/questions/1069981/set-volume-using-php-exec-and-amixer

putenv("PULSE_SERVER=/run/user/".getmyuid()."/pulse/native");
like image 770
Markus Kottländer Avatar asked Apr 26 '16 14:04

Markus Kottländer


4 Answers

Perhaps amixer isn't addressing the correct DBUS when run from apache. Try setting the DBUS_ADDRESS environment variable by invoking amixer from a shell script that sets the variable before running amixer.

dbus_amixer.sh

#! /bin/bash
DBUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/*/environ 2> /dev/null| sed 's/DBUS/\nDBUS/g' | tail -n 1`
if [ "x$DBUS_ADDRESS" != "x" ]; then
        export $DBUS_ADDRESS
        /usr/bin/amixer set Master 5%+
fi

(Code copied from Running command-line application from PHP as specific user)

amixer.php

<?php
echo exec('dbus_amixer.sh') . " \n";
like image 141
FuzzyTree Avatar answered Nov 14 '22 17:11

FuzzyTree


Try first running aplay -L and you should get output something like this:

pulse
    PulseAudio Sound Server
sysdefault:CARD=MID
    HDA Intel MID, ALC889 Analog
    Default Audio Device
front:CARD=MID,DEV=0
    HDA Intel MID, ALC889 Analog
    Front speakers
surround21:CARD=MID,DEV=0
    HDA Intel MID, ALC889 Analog
    2.1 Surround output to Front and Subwoofer speakers
...

Identify which of these is your device, then modify your amixer ... command to amixer -D device ..., for example amixer -D surround21:CARD=MID,DEV=0 set Master 5%+.

This may work. If not, try aplay -l (lowercase), and get the card number. Then, for example, if the card number is 1, try amixer -c 1 set Master 5%+.

like image 41
Candy Gumdrop Avatar answered Nov 14 '22 18:11

Candy Gumdrop


You say that your Apache user runs as your command line user. How far does the similarity extend? I notice that you use short path:

echo exec('amixer set Master 5%+')

...given that the user is the same, you might have the wrong path in Apache (PATH settings are not dependent on the user, they're in the user profile, and Apache might load a different profile altogether) - try placing the full path to amixer into the exec:

echo exec('/usr/local/bin/or/whatever/amixer set Master 5%+') . " \n";

Also, for debugging purposes, run shell_exec adding 2>&1 stderr redirect to the command line. This might yield some clue as to what exactly is failing.

You can run a more complex command to set up environment:

exec(`HOME=whatever FLAGS=somethingelse PATH=/usr/local/... /usr/local/bin/amixer... 2>&1`);

To know what the environment variables are, you can log as the user, verify that amixer works, dump the environment into a file:

set > set.txt

and check out set.txt for whatever values could apply to amixer. You can run another similar set from within Apache, and compare the results (actually I think that the environment is accessible also via phpinfo()).

like image 1
LSerni Avatar answered Nov 14 '22 17:11

LSerni


The best and more easy way to get this done is by using xdotool.

<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioMute");
?>

<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioRaiseVolume");
?>

<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioLowerVolume");
?>

I installed xdotool and configured the rc.xml file on ubuntu openbox with

 <!-- Keybinding for Volume management -->
   <keybind key="XF86AudioRaiseVolume">
     <action name="Execute">
       <command>amixer -D pulse set Master 10%+</command>
     </action>
  </keybind>
   <keybind key="XF86AudioLowerVolume">
     <action name="Execute">
       <command>amixer -D pulse set Master 10%-</command>
     </action>
   </keybind>
   <keybind key="XF86AudioMute">
     <action name="Execute">
       <command>amixer -D pulse set Master 100%-</command>
     </action>
  </keybind>

It works like a charm.

like image 1
rijotech Avatar answered Nov 14 '22 18:11

rijotech