00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include "stdinc.h"
00032
00033 #include <sys/ioctl.h>
00034 #include OSS_HEADER
00035
00036 #include "audio_file.h"
00037 #include "audio_output.h"
00038 #include "config.h"
00039 #include "gui.h"
00040
00041 #ifndef SNDCTL_DSP_GETPLAYVOL
00042 #define BUILD_OSS3_MIXER
00043 #endif
00044
00048 static int dev_fd;
00049 #if defined(BUILD_VOLUME) && defined(BUILD_OSS3_MIXER)
00050
00053 static int mix_fd;
00054 #endif
00055
00058 static unsigned int cur_srate = 0;
00062 static unsigned int cur_channels = 0;
00063
00064 int
00065 audio_output_open(void)
00066 {
00067 const char *dev;
00068
00069
00070 dev = config_getopt("audio.output.oss.device");
00071 if ((dev_fd = open(dev, O_WRONLY)) == -1) {
00072 g_printerr(_("Cannot open audio device \"%s\".\n"), dev);
00073 return (-1);
00074 }
00075
00076 #if defined(BUILD_VOLUME) && defined(BUILD_OSS3_MIXER)
00077
00078 dev = config_getopt("audio.output.oss.mixer");
00079 mix_fd = open(dev, O_RDWR);
00080 #endif
00081
00082 return (0);
00083 }
00084
00085 int
00086 audio_output_play(struct audio_file *fd)
00087 {
00088 int16_t buf[2048];
00089 int len;
00090 int fmt;
00091
00092 if ((len = audio_file_read(fd, buf, sizeof buf / sizeof(int16_t))) == 0)
00093 return (-1);
00094
00095 if (cur_srate != fd->srate || cur_channels != fd->channels) {
00096
00097 ioctl(dev_fd, SNDCTL_DSP_RESET, NULL);
00098
00099
00100 fmt = AFMT_S16_NE;
00101 if (ioctl(dev_fd, SNDCTL_DSP_SETFMT, &fmt) == -1)
00102 goto bad;
00103
00104
00105 if (ioctl(dev_fd, SNDCTL_DSP_SPEED, &fd->srate) == -1)
00106 goto bad;
00107
00108
00109 if (ioctl(dev_fd, SNDCTL_DSP_CHANNELS, &fd->channels) == -1)
00110 goto bad;
00111
00112
00113 cur_srate = fd->srate;
00114 cur_channels = fd->channels;
00115 }
00116
00117 len *= sizeof(int16_t);
00118 if (write(dev_fd, buf, len) != len)
00119 return (-1);
00120
00121 return (0);
00122 bad:
00123 gui_msgbar_warn(_("Sample rate or amount of channels not supported."));
00124
00125 cur_srate = 0;
00126 return (-1);
00127 }
00128
00129 void
00130 audio_output_close(void)
00131 {
00132 close(dev_fd);
00133 }
00134
00135 #ifdef BUILD_VOLUME
00136
00140 static int
00141 audio_output_volume_adjust(int n)
00142 {
00143 int vol, out;
00144
00145 #ifdef BUILD_OSS3_MIXER
00146 if (mix_fd < 0 ||
00147 ioctl(mix_fd, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1)
00148 #else
00149 if (ioctl(dev_fd, SNDCTL_DSP_GETPLAYVOL, &vol) == -1)
00150 #endif
00151 return (-1);
00152
00153
00154 vol = ((vol & 0x7f) + ((vol >> 8) & 0x7f)) / 2;
00155 vol = CLAMP(vol + n, 0, 100);
00156 out = (vol << 8) | vol;
00157
00158 #ifdef BUILD_OSS3_MIXER
00159 if (ioctl(mix_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &out) == -1)
00160 #else
00161 if (ioctl(dev_fd, SNDCTL_DSP_SETPLAYVOL, &out) == -1)
00162 #endif
00163 return (-1);
00164
00165 return (vol);
00166 }
00167
00168 int
00169 audio_output_volume_up(void)
00170 {
00171 return audio_output_volume_adjust(4);
00172 }
00173
00174 int
00175 audio_output_volume_down(void)
00176 {
00177 return audio_output_volume_adjust(-4);
00178 }
00179 #endif