I originally posted this at http://blogs.sun.com/brendan/entry/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 my C program:
/* volumeset.c - set Sun's /dev/audio play volume */ #include#include #include #include #include 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.