Monday Mar 05, 2007

Audio Volume CLI

While Solaris has a fancy GNOME based desktop called JDS3, other desktop environments are available and work fine. FVWM2 is a fast alternative with a modest set of features, and is available on the Software Companion CD (which you may already have a copy of).

If you have installed fvwm2 from the companion CD and would like to try it, the easiest way is to enter a fail safe session from the login screen, then run the binary - /opt/sfw/bin/fvwm2. The proper way is to create config files under /etc/dt/config, so that the login screen provides FVWM as an option.

After getting fvwm2 running, I found my volume up/down/mute keys on this Sun type 7 keyboard didn't work. An internet search didn't find any solutions. To get these keys to work, I wrote a short C program to ioctl /dev/audioctl, and added some lines to the .fvwmrc file. I'm writing this quick blog entry to help the next person doing the same Internet search. If there is a better way to do this in Solaris already (like a shipped binary), I missed it!

This is the C program,

/\* volumeset.c - set Sun's /dev/audio play volume \*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/audioio.h>

void
usage(char \*name)
{
        (void) printf("USAGE: %s [+|-]volume_percent\\n", name);
        (void) printf("   eg,\\n");
        (void) printf("       %s 100     # maximum volume\\n", name);
        (void) printf("       %s +5      # plus 5 percent\\n", name);
        exit(1);
}

int
main(int argc, char \*argv[])
{
        audio_info_t ai;
        int fd, vol, mod, gain;

        if (argc < 2)
                usage(argv[0]);

        switch (argv[1][0]) {
                case '+':
                        mod = 1;
                        vol = atoi(&argv[1][1]);
                        break;
                case '-':
                        mod = -1;
                        vol = atoi(&argv[1][1]);
                        break;
                case '0'...'9':
                        mod = 0;
                        vol = atoi(argv[1]);
                        if (vol > 100 || vol < 0) {
                                (void) printf("ERROR: volume must be "
                                    "between 0 and 100.\\n");
                                exit(4);
                        }
                        break;
                default:
                        usage(argv[0]);
        }

        if (mod != 0 && vol == 0)
                usage(argv[0]);

        if ((fd = open("/dev/audioctl", O_RDONLY)) == -1) {
                (void) perror("can't open /dev/audioctl");
                exit(2);
        }

        if (ioctl(fd, AUDIO_GETINFO, &ai) == -1) {
                (void) perror("fetching audio state failed");
                exit(3);
        }

        if (mod == 0)
                gain = (vol \* 255) / 100;
        else
                gain = ai.play.gain + (mod \* vol \* 255) / 100;
        if (gain < 0)
                gain = 0;
        if (gain > 255)
                gain = 255;

        ai.play.gain = gain;
        ai.output_muted = gain == 0 ? 1 : 0;

        if (ioctl(fd, AUDIO_SETINFO, &ai) == -1) {
                (void) perror("setting audio state failed");
                exit(4);
        }

        (void) close(fd);

        return (0);
}
If you don't have Sun's C compiler installed, you can compile it using /usr/sfw/bin/gcc -o volumeset volumeset.c.

The following are the lines I added to ~/.fvwm/.fvwm2rc to bind the audio keys on the top left to the volumeset program (copied to /usr/local/bin); these bindings probably work for type 6 keyboards as well (haven't tried),

Key SunAudioMute A       A       Exec /usr/local/bin/volumeset 0
Key SunAudioLowerVolume A A      Exec /usr/local/bin/volumeset -15
Key SunAudioRaiseVolume A A      Exec /usr/local/bin/volumeset +15
The above lines bind the keys to mute the volume, decrease by 15% or increase by 15% (it may be better to make the mute behave as a toggle, rather than always mute). After restarting fvwm, my audio keys now work fine.
About

Brendan Gregg, Fishworks engineer

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today