29 |
|
|
30 |
#include "rdesktop.h" |
#include "rdesktop.h" |
31 |
#include "rdpsnd.h" |
#include "rdpsnd.h" |
32 |
|
#include "rdpsnd_dsp.h" |
33 |
#include <unistd.h> |
#include <unistd.h> |
34 |
#include <fcntl.h> |
#include <fcntl.h> |
35 |
#include <errno.h> |
#include <errno.h> |
43 |
static int snd_rate; |
static int snd_rate; |
44 |
static short samplewidth; |
static short samplewidth; |
45 |
static char *dsp_dev; |
static char *dsp_dev; |
46 |
|
static struct audio_driver oss_driver; |
47 |
|
|
48 |
BOOL |
BOOL |
49 |
oss_open(void) |
oss_open(void) |
116 |
return False; |
return False; |
117 |
} |
} |
118 |
|
|
119 |
|
oss_driver.need_resampling = 0; |
120 |
snd_rate = pwfx->nSamplesPerSec; |
snd_rate = pwfx->nSamplesPerSec; |
121 |
if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1) |
if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1) |
122 |
{ |
{ |
123 |
perror("SNDCTL_DSP_SPEED"); |
int rates[] = { 44100, 48000, 0 }; |
124 |
close(g_dsp_fd); |
int *prates = rates; |
125 |
return False; |
|
126 |
|
while (*prates != 0) |
127 |
|
{ |
128 |
|
if ((pwfx->nSamplesPerSec != *prates) |
129 |
|
&& (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, prates) != -1)) |
130 |
|
{ |
131 |
|
oss_driver.need_resampling = 1; |
132 |
|
snd_rate = *prates; |
133 |
|
if (rdpsnd_dsp_resample_set |
134 |
|
(snd_rate, pwfx->wBitsPerSample, pwfx->nChannels) == False) |
135 |
|
{ |
136 |
|
error("rdpsnd_dsp_resample_set failed"); |
137 |
|
close(g_dsp_fd); |
138 |
|
return False; |
139 |
|
} |
140 |
|
|
141 |
|
break; |
142 |
|
} |
143 |
|
prates++; |
144 |
|
} |
145 |
|
|
146 |
|
if (*prates == 0) |
147 |
|
{ |
148 |
|
perror("SNDCTL_DSP_SPEED"); |
149 |
|
close(g_dsp_fd); |
150 |
|
return False; |
151 |
|
} |
152 |
} |
} |
153 |
|
|
154 |
/* try to get 12 fragments of 2^12 bytes size */ |
/* try to get 12 fragments of 2^12 bytes size */ |
182 |
void |
void |
183 |
oss_volume(uint16 left, uint16 right) |
oss_volume(uint16 left, uint16 right) |
184 |
{ |
{ |
|
static BOOL use_dev_mixer = False; |
|
185 |
uint32 volume; |
uint32 volume; |
|
int fd_mix = -1; |
|
186 |
|
|
187 |
volume = left / (65536 / 100); |
volume = left / (65536 / 100); |
188 |
volume |= right / (65536 / 100) << 8; |
volume |= right / (65536 / 100) << 8; |
189 |
|
|
|
if (use_dev_mixer) |
|
|
{ |
|
|
if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1) |
|
|
{ |
|
|
perror("open /dev/mixer"); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) |
|
|
{ |
|
|
perror("MIXER_WRITE(SOUND_MIXER_PCM)"); |
|
|
return; |
|
|
} |
|
|
|
|
|
close(fd_mix); |
|
|
} |
|
|
|
|
190 |
if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) |
if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) |
191 |
{ |
{ |
192 |
perror("MIXER_WRITE(SOUND_MIXER_PCM)"); |
warning("hardware volume control unavailable, falling back to software volume control!\n"); |
193 |
use_dev_mixer = True; |
oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set; |
194 |
|
rdpsnd_dsp_softvol_set(left, right); |
195 |
return; |
return; |
196 |
} |
} |
197 |
} |
} |
266 |
struct audio_driver * |
struct audio_driver * |
267 |
oss_register(char *options) |
oss_register(char *options) |
268 |
{ |
{ |
|
static struct audio_driver oss_driver; |
|
|
|
|
269 |
oss_driver.wave_out_write = rdpsnd_queue_write; |
oss_driver.wave_out_write = rdpsnd_queue_write; |
270 |
oss_driver.wave_out_open = oss_open; |
oss_driver.wave_out_open = oss_open; |
271 |
oss_driver.wave_out_close = oss_close; |
oss_driver.wave_out_close = oss_close; |
276 |
oss_driver.name = xstrdup("oss"); |
oss_driver.name = xstrdup("oss"); |
277 |
oss_driver.description = |
oss_driver.description = |
278 |
xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"); |
xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"); |
279 |
|
oss_driver.need_byteswap_on_be = 0; |
280 |
|
oss_driver.need_resampling = 0; |
281 |
oss_driver.next = NULL; |
oss_driver.next = NULL; |
282 |
|
|
283 |
if (options) |
if (options) |