ALSA_DIR =
endif
-SUBDIRS = $(ALSA_DIR) oss-redir
+SUBDIRS = $(ALSA_DIR) oss-redir test
dist-hook:
echo $(VERSION) >> version
libaoss_la_SOURCES = alsa-oss.c
libaoss_la_LIBADD = -ldl -lalsatoss
+libalsatoss_la_CFLAGS = @ALSA_CFLAGS@
libalsatoss_la_SOURCES = pcm.c mixer.c
-libalsatoss_la_LIBADD = -lasound
+libalsatoss_la_LDADD = @ALSA_LDFLAGS@
+libalsatoss_la_LIBADD = @ALSA_LIBS@
clean:
rm -f aoss
static ops_t ops[FD_CLASSES];
typedef struct {
- int count;
fd_class_t class;
void *mmap_area;
} fd_t;
}
} else if (!strncmp(file, "/dev/mixer", 10)) {
fd = lib_oss_mixer_open(file, oflag);
- fds[fd]->class = FD_OSS_MIXER;
+ if (fd >= 0) {
+ fds[fd] = calloc(sizeof(fd_t), 1);
+ if (fds[fd] == NULL) {
+ ops[FD_OSS_MIXER].close(fd);
+ errno = ENOMEM;
+ return -1;
+ }
+ fds[fd]->class = FD_OSS_MIXER;
+ }
} else {
fd = _open(file, oflag, mode);
if (fd >= 0)
--- /dev/null
+#!/bin/sh
+
+# A simple script to facilitate the use of the OSS compatibility library.
+# Usage:
+# testaoss <command> <command options and arguments>
+
+prefix=@top_srcdir@
+ALSA_OSS_WRAPPER=1 LD_PRELOAD=${prefix}/alsa/.libs/libaoss.so $*
AM_CONDITIONAL(WITH_AOSS, test x$with_aoss = xyes)
if test "$with_aoss" = "yes"; then
+ OLD_CFLAGS=$CFLAGS ; CFLAGS=""
+ OLD_LDFLAGS=$LDFLAGS ; LDFLAGS=""
+ OLD_LIBS=$LIBS ; LIBS=""
AM_PATH_ALSA(0.9.0)
+ ALSA_CFLAGS=$CFLAGS
+ ALSA_LDFLAGS=$LDFLAGS
+ ALSA_LIBS=$LIBS
+ AC_SUBST(ALSA_CFLAGS)
+ AC_SUBST(ALSA_LDFLAGS)
+ AC_SUBST(ALSA_LIBS)
+ CFLAGS=$OLD_CFLAGS
+ LDFLAGS=$OLD_LDFLAGS
+ LIBS=$OLD_LIBS
fi
-AC_OUTPUT(Makefile alsa/Makefile alsa/aoss oss-redir/Makefile)
+AC_OUTPUT(Makefile alsa/Makefile alsa/aoss oss-redir/Makefile test/Makefile \
+ alsa/testaoss test/testaoss)
-ossredirincludedir = ${includedir}
+ossredirincludedir = ${includedir}/sound
ossredirinclude_HEADERS = oss-redir.h
static int (*x_oss_pcm_open)(const char *pathname, int flags);
static int (*x_oss_pcm_close)(int fd);
+int (*oss_pcm_nonblock)(int fd, int nonblock);
ssize_t (*oss_pcm_read)(int fd, void *buf, size_t count);
ssize_t (*oss_pcm_write)(int fd, const void *buf, size_t count);
void * (*oss_pcm_mmap)(void *start, size_t length, int prot, int flags, int fd, off_t offset);
#define OSS_WAIT_EVENT_WRITE (1<<1)
#define OSS_WAIT_EVENT_ERROR (1<<2)
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern int oss_pcm_open(const char *pathname, int flags, ...);
extern int oss_pcm_close(int fd);
extern int (*oss_pcm_nonblock)(int fd, int nonblock);
extern int oss_mixer_close(int fd);
extern int (*oss_mixer_ioctl)(int fd, unsigned long int request, ...);
+#ifdef __cplusplus
+}
+#endif
#endif /* __OSS_REDIR_H */
-check_PROGRAMS=mmap_test mmap_test_redir
+check_PROGRAMS=mmap_test lmixer
-mmap_test_redir_LDADD=../oss-redir/libossredir.la
+mmap_test_LDADD=../oss-redir/libossredir.la
+lmixer_LDADD=../oss-redir/libossredir.la
+lmixer_SOURCES=lmixer.cc
INCLUDES=-I$(top_srcdir)/oss-redir
CFLAGS=-static -Wall -pipe -g
--- /dev/null
+// lmixer
+//
+// Written by Brandon Zehm
+// caspian@linuxfreak.com
+//
+// This software is released under the GNU GPL license.
+// For details see http://www.gnu.org/copyleft/gpl.html
+//
+// If you have patches, suggestions, comments, or anything
+// else to tell me, please feel free to email me.
+//
+
+#define MIXERVERSION "1.0.7"
+#define MIXERDEV "/dev/mixer"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "mixctl.h"
+
+
+// Initialize functions
+void help();
+void version();
+void scanArgs(int argc, char **argv);
+void ShowChannelInfo();
+int VerifyChannelName();
+int open_mixer();
+
+
+// Define Variables
+char mixdev[256]=MIXERDEV; // The var with the mixer device
+int volume=255; // Set volume to a value out of range
+int channel=255; // Set channel to a value out of range
+char channel_name[32]="BLANK"; //
+
+// Initialize interface to mixer.h
+MixCtl *mixctl;
+
+
+
+
+
+
+////////////////////////////////////////////////////////
+// Sub: main()
+// Input: argc and **argv
+////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ // Get command line parameters.
+ scanArgs(argc, argv);
+
+ // If neither the volume or the channel got set print help.
+ if ((volume == 255) && (channel == 255)) {
+ help();
+ exit(1);
+ }
+
+ // Check to see if the volume got set
+ if (volume == 255) {
+ printf ("You must set a volume!\n");
+ help();
+ exit(1);
+ }
+
+ // Check to see if the volume got set
+ if(strcmp(channel_name, "BLANK")==0) {
+ printf ("You must set a mixer channel!\n");
+ help();
+ exit(1);
+ }
+
+
+ // If we get here we assume we are doing the defualt operation
+ // which is:
+ // 1. open mixer
+ // 2. write volume to a channel
+ // 3. quit
+
+
+ // Open the mixer or die
+ if (open_mixer() != 1) {
+ exit(1);
+ }
+
+ // Verify that the incoming channel_name is valid
+ // and set 'channel' to the corresponding channel number.
+ if (VerifyChannelName() == 0) {
+ printf("\'%s\' is not a valid channel name!\n", channel_name);
+ exit(1);
+ }
+
+ // Write the volume
+ mixctl->setBoth(channel,volume,volume);
+ mixctl->writeVol(channel);
+
+
+ // Exit
+ delete mixctl;
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////
+// Sub: scanArgs()
+// Input: argc and *argv
+// Output: Sets initial variables
+// Description: Receives incoming data and directs
+// the flow of the program.
+////////////////////////////////////////////////////////
+void scanArgs(int argc, char *argv[]){
+ for(int i=1;i<argc;i++){
+ // Help
+ if(strcmp(argv[i], "-h")==0 || strcmp(argv[i], "--help")==0){
+ help();
+ exit(0);
+ }
+ // Set Mixer Device
+ if(strcmp(argv[i], "-d")==0 || strcmp(argv[i], "--device")==0){
+ if(i<argc-1){
+ i++;
+ sprintf(mixdev, "%s", argv[i]);
+ }
+ continue;
+ }
+ // Set new volume
+ if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "--volume")==0){
+ if(i<argc-1){
+ i++;
+ volume = atoi(argv[i]);
+ }
+ continue;
+ }
+ // Set new mixer channel
+ if(strcmp(argv[i], "-c")==0 || strcmp(argv[i], "--channel")==0){
+ if(i<argc-1){
+ i++;
+ sprintf(channel_name, "%s", argv[i]);
+ }
+ continue;
+ }
+ // Show mixer information
+ if(strcmp(argv[i], "-i")==0 || strcmp(argv[i], "--info")==0){
+ if (open_mixer() != 1) {
+ exit(1);
+ }
+ ShowChannelInfo();
+ exit(0);
+ }
+ // Show version information
+ if(strcmp(argv[i], "-V")==0 || strcmp(argv[i], "--version")==0){
+ version();
+ exit(0);
+ }
+ }
+}
+
+
+
+
+
+
+//////////////////////////////////////////////////////////
+// Sub: Help()
+// Input: void
+// Output:
+// Description: Prints the help message.
+/////////////////////////////////////////////////////////
+void help() {
+ printf("\n");
+ printf("lmixer v%s\n", MIXERVERSION);
+ printf(" \n");
+ printf("Usage: lmixer [options] \n");
+ printf(" \n");
+ printf(" -c,--channel <channel name> Mixer channel to adjust \n");
+ printf(" -v,--volume <volume> Volume (1-100) \n");
+ printf(" -d,--device <mixer device> Use specified mixer device \n");
+ printf(" -i,--info Shows the volume of each mixer device \n");
+ printf(" -V,--version Display version information \n");
+ printf(" -h,--help Display this help screen \n");
+ printf(" \n");
+ printf("Typical useage: 'lmixer -c bass -v 85' \n");
+ printf("\n");
+}
+
+
+
+//////////////////////////////////////////////////////////
+// Sub: version()
+// Input: void
+// Description: Prints version informaion
+/////////////////////////////////////////////////////////
+void version() {
+ printf("lmixer version %s\n", MIXERVERSION);
+}
+
+
+
+
+////////////////////////////////////////////////////////
+// Sub: open_mixer()
+// Input: int
+// Output: Returns 1 on success 0 on failure.
+// Description: Opens the mixer device or dies.
+////////////////////////////////////////////////////////
+int open_mixer () {
+ // Open the mixer, and verify it worked.
+ mixctl=new MixCtl(mixdev);
+ if(!mixctl->openOK()) {
+ fprintf(stdout,"Unable to open mixer device: %s\n", mixdev);
+ return(0);
+ }
+ return(1);
+}
+
+
+
+
+
+
+////////////////////////////////////////////////////////
+// Sub: ShowChannelInfo()
+// Input: void
+// Output: STDOUT
+// Description: Shows a list of channels and their
+// current volumes.
+////////////////////////////////////////////////////////
+void ShowChannelInfo () {
+ for (int i = 0; i < mixctl->getNrDevices(); i++) { // For every device,
+ if (mixctl->getSupport(i)) { // if the device exists,
+ volume = mixctl->readVol(i,1); // Get the volume
+ printf ("%s\t%d\n", mixctl->getName(i), volume); // and print a line.
+ }
+ }
+}
+
+
+
+////////////////////////////////////////////////////////
+// Sub: VerifyChannelName()
+// Input: Reads global var channel_name
+// Output: returns a 1 on success 0 on failure
+// Description: Checks to see if 'channel_name' is
+// a valid mixer device, and if it
+// is it sets 'channel' to the number of
+// that device.
+////////////////////////////////////////////////////////
+int VerifyChannelName () {
+ for (int i = 0; i < mixctl->getNrDevices(); i++) { // For every device,
+ if (mixctl->getSupport(i)) { // if the device exists,
+ if(strcmp(channel_name, mixctl->getName(i))==0) {
+ channel = i;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+// mixctl.h - MixCtl class provides control of audio mixer functions
+// 05/09/98 Release 1.0 Beta1
+// Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
+// This software comes with ABSOLUTELY NO WARRANTY
+// This software is free software, and you are welcome to redistribute it.
+
+// Although mixctl.h is an integral part of lmixer, it may also be distributed seperately.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef __NetBSD__
+#include <soundcard.h>
+#endif
+#ifdef __FreeBSD__
+#include <machine/soundcard.h>
+#endif
+#ifdef __linux__
+#include <linux/soundcard.h>
+#endif
+#include <oss-redir.h>
+
+class MixCtl
+{
+public:
+ MixCtl(char *dname){
+ device=(char *)malloc(sizeof(char)*(strlen(dname)+1));
+ strcpy(device,dname);
+ if(mixfdopen=(mixfd=oss_mixer_open(device,O_RDONLY | O_NONBLOCK))!=-1){
+ nrdevices=SOUND_MIXER_NRDEVICES;
+ char *devnames[]=SOUND_DEVICE_NAMES;
+ char *devlabels[]=SOUND_DEVICE_LABELS;
+ if (oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_DEVMASK, &devmask)<0)
+ fprintf(stderr, "SOUND_MIXER_READ_DEVMASK failed\n");
+ if (oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_STEREODEVS, &stmask)<0)
+ fprintf(stderr, "SOUND_MIXER_READ_STEREODEVS failed\n");
+ if (oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_RECMASK, &recmask)<0)
+ fprintf(stderr, "SOUND_MIXER_READ_RECMASK failed\n");
+ if (oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_CAPS, &caps)<0)
+ fprintf(stderr, "SOUND_MIXER_READ_CAPS failed\n");
+ mixdevs=(struct MixDev *)malloc(sizeof(struct MixDev)*nrdevices);
+ int mixmask=1;
+ for(int i=0;i<nrdevices;i++){
+ mixdevs[i].support=devmask & mixmask;
+ mixdevs[i].stereo=stmask & mixmask;
+ mixdevs[i].records=recmask & mixmask;
+ mixdevs[i].mask=mixmask;
+ mixdevs[i].name=devnames[i];
+ mixdevs[i].label=devlabels[i];
+ mixmask*=2;
+ }
+ doStatus();
+ }
+ }
+ ~MixCtl(){
+ if(mixfdopen){
+ if(mixdevs!=NULL)
+ free(mixdevs);
+ oss_mixer_close(mixfd);
+ }
+ }
+ bool openOK(){
+ return mixfdopen;
+ }
+ void doStatus(){
+ oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc);
+ for(int i=0;i<nrdevices;i++){
+ if(mixdevs[i].support)
+ oss_mixer_ioctl(mixfd, MIXER_READ(i), &mixdevs[i].value);
+ mixdevs[i].recsrc=(recsrc & mixdevs[i].mask);
+ }
+ }
+
+ // Return volume for a device, optionally reading it from device first.
+ // Can be used as a way to avoid calling doStatus().
+ int readVol(int dev, bool read){
+ if(read)
+ oss_mixer_ioctl(mixfd, MIXER_READ(dev), &mixdevs[dev].value);
+ return mixdevs[dev].value/256;
+ }
+
+ // Return left and right componenets of volume for a device.
+ // If you are lazy, you can call readVol to read from the device, then these
+ // to get left and right values.
+ int readLeft(int dev){
+ return mixdevs[dev].value%256;
+ }
+ int readRight(int dev){
+ return mixdevs[dev].value/256;
+ }
+
+ // Write volume to device. Use setVolume, setLeft and setRight first.
+ void writeVol(int dev){
+ oss_mixer_ioctl(mixfd, MIXER_WRITE(dev), &mixdevs[dev].value);
+ }
+
+ // Set volume (or left or right component) for a device. You must call writeVol to write it.
+ void setVol(int dev, int value){
+ mixdevs[dev].value=value;
+ }
+ void setBoth(int dev, int l, int r){
+ mixdevs[dev].value=256*r+l;
+ }
+ void setLeft(int dev, int l){
+ int r;
+ if(mixdevs[dev].stereo)
+ r=mixdevs[dev].value/256;
+ else
+ r=l;
+ mixdevs[dev].value=256*r+l;
+ }
+ void setRight(int dev, int r){
+ int l;
+ if(mixdevs[dev].stereo)
+ l=mixdevs[dev].value%256;
+ else
+ l=r;
+ mixdevs[dev].value=256*r+l;
+ }
+
+ // Return record source value for a device, optionally reading it from device first.
+ bool readRec(int dev, bool read){
+ if(read){
+ oss_mixer_ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc);
+ mixdevs[dev].recsrc=(recsrc & mixdevs[dev].mask);
+ }
+ return mixdevs[dev].recsrc;
+ }
+
+ // Write record source values to device. Use setRec first.
+ void writeRec(){
+ oss_mixer_ioctl(mixfd, SOUND_MIXER_WRITE_RECSRC, &recsrc);
+ }
+
+ // Make a device (not) a record source.
+ void setRec(int dev, bool rec){
+ if(rec){
+ if(caps & SOUND_CAP_EXCL_INPUT)
+ recsrc=mixdevs[dev].mask;
+ else
+ recsrc|=mixdevs[dev].mask;
+ }
+ else
+ recsrc&=~mixdevs[dev].mask;
+ }
+
+ // Return various other info
+ char *getDevName(){
+ return device;
+ }
+ // Return the number of mixer devices..
+ // note: check the validity of each with getSupport
+ // before using.
+ int getNrDevices(){
+ return nrdevices;
+ }
+ int getCapabilities(){
+ return caps;
+ }
+ // Is this dev valid?
+ // Example: if (mixctl->getSupport(dev)) { "The channel is valid" }
+ bool getSupport(int dev){
+ return mixdevs[dev].support;
+ }
+ bool getStereo(int dev){
+ return mixdevs[dev].stereo;
+ }
+ bool getRecords(int dev){
+ return mixdevs[dev].records;
+ }
+ // Get the name of int dev..
+ // example: printf("Channel %d's name is %s", channel, mixctl->getName(channel));
+ char *getName(int dev){
+ return mixdevs[dev].name;
+ }
+ char *getLabel(int dev){
+ return mixdevs[dev].label;
+ }
+
+private:
+ int mixfd;
+ int mixfdopen;
+ char *device;
+
+ struct MixDev{
+ bool support;
+ bool stereo;
+ bool recsrc;
+ bool records;
+ char *name;
+ char *label;
+ int value;
+ int mask;
+ };
+
+ int nrdevices; // maximum number of devices
+ int devmask; // supported devices
+ int stmask; // stereo devices
+ int recmask; // devices which can be recorded from
+ int caps; // capabilities
+ int recsrc; // devices which are being recorded from
+ struct MixDev *mixdevs;
+};
fd_set writeset;\r
\r
close(0);\r
- if ((fd=open("/dev/dsp", O_RDWR, 0))==-1)\r
+ if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1)\r
{\r
perror("/dev/dsp");\r
exit(-1);\r
*/\r
\r
tmp = 48000;\r
- ioctl(fd, SNDCTL_DSP_SPEED, &tmp);\r
+ oss_pcm_ioctl(fd, SNDCTL_DSP_SPEED, &tmp);\r
printf("Speed set to %d\n", tmp);\r
\r
/*\r
}\r
else perror("smpl");\r
\r
- if (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps)==-1)\r
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETCAPS, &caps)==-1)\r
{\r
perror("/dev/dsp");\r
fprintf(stderr, "Sorry but your sound driver is too old\n");\r
* The application should also check for DSP_CAP_MMAP bit but this\r
* version of driver doesn't have it yet.\r
*/\r
-/* ioctl(fd, SNDCTL_DSP_SETSYNCRO, 0); */\r
+/* oss_pcm_ioctl(fd, SNDCTL_DSP_SETSYNCRO, 0); */\r
\r
/*\r
* You need version 3.5-beta7 or later of the sound driver before next\r
* select call returns.\r
*/\r
\r
- ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);\r
+ oss_pcm_ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);\r
\r
/*\r
* Compute total size of the buffer. It's important to use this value\r
* in mmap() call.\r
*/\r
\r
- if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)==-1)\r
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)==-1)\r
{\r
perror("GETOSPACE");\r
exit(-1);\r
*/\r
\r
tmp = 0;\r
- ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);\r
+ oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);\r
printf("Trigger set to %08x\n", tmp);\r
\r
/*\r
*/\r
\r
tmp = PCM_ENABLE_OUTPUT;\r
- ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);\r
+ oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);\r
printf("Trigger set to %08x\n", tmp);\r
\r
/*\r
* the beginning of total buffer area).\r
*/\r
\r
- if (ioctl(fd, SNDCTL_DSP_GETOPTR, &count)==-1)\r
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOPTR, &count)==-1)\r
{\r
perror("GETOPTR");\r
exit(-1);\r
printf( ">>>> open (2)\n" ); fflush( stdout );
- if ((fd=open("/dev/dsp", O_RDWR, 0))==-1)\r
+ if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1)\r
{\r
perror("/dev/dsp");\r
exit(-1);\r
--- /dev/null
+#!/bin/sh
+
+# A simple script to facilitate the use of the OSS compatibility library.
+# Usage:
+# testaoss <command> <command options and arguments>
+
+prefix=@top_srcdir@
+ALSA_OSS_WRAPPER=1 LD_PRELOAD=${prefix}/alsa/.libs/libaoss.so $*