amboxer21 has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I have a small program I put together. Everything works fine except when I hit the UP button. It resets the volume back to zero. I am trying to grab the current volume and then add one with the up button click. Can someone help me? I would greatly appreciate it!



#!/usr/bin/perl-w use Tk; use strict; my $mw = MainWindow->new; $mw->geometry("250x100"); $mw->title("Volume"); $mw->Label(-text=>'Volume Control UI')->pack(-side=> 'top'); $mw->Button(-text=>'SET', -command=>\&SetVol)->pack(-side=> 'left', -a +nchor=> 'sw'); $mw->Button(-text=>'MUTE', -command=>\&VolumeMute)->pack(-side=> 'left +', -anchor=> 'sw'); $mw->Button(-text=>'UP', -command=>\&SetVolPlus10)->pack(-side=>'left' +, -anchor=>'sw'); my $Entry = $mw->Entry()->pack(-side=> 'left', -anchor=> 'sw', -pady=> + 3); my $VolCur = q(/usr/bin/amixer get Master | grep -o "[0-9].%" | awk '! +x[$0]++'); sub SetVol { my $Etext = $Entry->get(); system("amixer set 'Master' $Etext"); } sub VolumeMute { system("amixer set 'Master' 0%"); } my $UC = $VolCur; sub SetVolPlus10 { system($VolCur); $UC+1; system("amixer set 'Master' $UC"); } MainLoop;

Replies are listed 'Best First'.
Re: Store system call in a variable
by toolic (Bishop) on Sep 07, 2014 at 01:37 UTC
    To capture the output of a command, use qx instead of system.
Re: Store system call in a variable
by zentara (Cardinal) on Sep 07, 2014 at 10:34 UTC
    Using system, or qx, or similar methods will block the Tk eventloop, although you may get away with it it for such short commands. To do it properly, you want to use the non-blocking IPC methods available to Tk's eventloop.
    See ztk-v4l-video-bloger/recorder for an example. I'm not sure if the amixer commands are still current with newer alsa versions, but it does show the method for using amixer with Tk. You can get a list of all alsamixer settings, just google for how.

    The important part of the code above is this:

    #setup a shell thru IPC to carry out different # mixer and v4l2 control commands my $pidcon = open3(\*CON,0,0,'/bin/sh'); # then later use it like this &mic_con(1); #turn on Mic sub mic_con{ my $con = shift; if($con == 1){ #turn Mic on to max for recording #turn off playback to avoid feedback squeal print CON "amixer cset name='AC97 Playback Volume', 0\n"; #switch the capture to Mic print CON "amixer sset Mic Capture cap\n"; #turn up maximum Mic gain print CON "amixer cset name='Mic Playback Volume', 100\n"; #turn on Mic +20db boost print CON "amixer cset name='Mic Boost (+20dB)', 1\n"; } if($con == 0){ #restore old Line settings #turn off Mic by changing capture to Line print CON "amixer sset Line Capture cap\n"; #turn off Mic +20db boost print CON "amixer cset name='Mic Boost (+20dB)', 0\n"; #restore normal capture volume print CON "amixer cset name='AC97 Playback Volume', 88\n"; } }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Store system call in a variable
by Anonymous Monk on Sep 07, 2014 at 01:43 UTC

    Use the qx operator, also known as backticks. For example my $out = `/usr/bin/amixer get Master`; will call that command and store its output in $out. Even better, use system and capture from IPC::System::Simple, that's got better error handling.

    The manipulations you're currently doing with grep and awk can be done in Perl. If I understand correctly you want to get the first value that looks like a percentage. You could do this via e.g. my ($vol) = $out=~/\b(\d+)%/;

    In your current code, $VolCur contains a value like "26%", when you add one to that you get a value of 27 (and a warning, which is why my code above doesn't grab the percentage sign into $vol), which you would need to add a percent sign to get amixer to accept it as a percentage value.

    Lastly, I don't think your line system($VolCur); is doing anything useful, since it's just trying to call commands named after percentages... that's another reason why in general, you should always check for errors from system calls, see for example system on how to do that.