ReactOS 0.4.15-dev-7677-g8209aa5
rdpsnd_oss.c File Reference
#include "rdesktop.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
Include dependency graph for rdpsnd_oss.c:

Go to the source code of this file.

Classes

struct  audio_packet
 

Macros

#define MAX_QUEUE   10
 

Functions

BOOL wave_out_open (void)
 
void wave_out_close (void)
 
BOOL wave_out_format_supported (WAVEFORMATEX *pwfx)
 
BOOL wave_out_set_format (WAVEFORMATEX *pwfx)
 
void wave_out_volume (uint16 left, uint16 right)
 
void wave_out_write (STREAM s, uint16 tick, uint8 index)
 
void wave_out_play (void)
 

Variables

int This dsp_
 
BOOL This dsp_bu = False
 
static int g_snd_rate
 
static short g_samplewidth
 
static BOOL g_driver_broken = False
 
static struct audio_packet packet_queue [MAX_QUEUE]
 
static unsigned int queue_hi
 
static unsigned int queue_lo
 

Macro Definition Documentation

◆ MAX_QUEUE

#define MAX_QUEUE   10

Definition at line 38 of file rdpsnd_oss.c.

Function Documentation

◆ wave_out_close()

void wave_out_close ( void  )

Definition at line 76 of file rdpsnd_oss.c.

77{
78 close(This->dsp_);
79}
#define close
Definition: acwin.h:98

◆ wave_out_format_supported()

BOOL wave_out_format_supported ( WAVEFORMATEX pwfx)

Definition at line 82 of file rdpsnd_oss.c.

83{
84 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
85 return False;
86 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
87 return False;
88 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
89 return False;
90
91 return True;
92}
#define WAVE_FORMAT_PCM
Definition: constants.h:425
#define False
Definition: types.h:25
#define True
Definition: types.h:24
WORD wBitsPerSample
Definition: audioclient.idl:45

◆ wave_out_open()

BOOL wave_out_open ( void  )

Definition at line 55 of file rdpsnd_oss.c.

56{
57 char *dsp_dev = getenv("AUDIODEV");
58
59 if (dsp_dev == NULL)
60 {
61 dsp_dev = xstrdup("/dev/dsp");
62 }
63
64 if ((This->dsp_ = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
65 {
66 perror(dsp_dev);
67 return False;
68 }
69
70 /* Non-blocking so that user interface is responsive */
71 fcntl(This->dsp_, F_SETFL, fcntl(This->dsp_, F_GETFL) | O_NONBLOCK);
72 return True;
73}
#define O_WRONLY
Definition: acwin.h:111
#define open
Definition: acwin.h:95
char * xstrdup(const char *s)
Definition: uimain.c:768
#define NULL
Definition: types.h:112
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
#define O_NONBLOCK
Definition: port.h:158

◆ wave_out_play()

void wave_out_play ( void  )

Definition at line 231 of file rdpsnd_oss.c.

232{
233 struct audio_packet *packet;
234 ssize_t len;
235 STREAM out;
236 static long startedat_us;
237 static long startedat_s;
238 static BOOL started = False;
239 struct timeval tv;
240 audio_buf_info info;
241
242 while (1)
243 {
244 if (queue_lo == queue_hi)
245 {
246 This->dsp_bu = 0;
247 return;
248 }
249
251 out = &packet->s;
252
253 if (!started)
254 {
255 gettimeofday(&tv, NULL);
256 startedat_us = tv.tv_usec;
257 startedat_s = tv.tv_sec;
258 started = True;
259 }
260
261 len = out->end - out->p;
262
263 if (!g_driver_broken)
264 {
265 memset(&info, 0, sizeof(info));
266 if (ioctl(This->dsp_, SNDCTL_DSP_GETOSPACE, &info) == -1)
267 {
268 perror("SNDCTL_DSP_GETOSPACE");
269 return;
270 }
271
272 if (info.fragments == 0)
273 {
274 This->dsp_bu = 1;
275 return;
276 }
277
278 if (info.fragments * info.fragsize < len
279 && info.fragments * info.fragsize > 0)
280 {
281 len = info.fragments * info.fragsize;
282 }
283 }
284
285
286 len = write(This->dsp_, out->p, len);
287 if (len == -1)
288 {
289 if (errno != EWOULDBLOCK)
290 perror("write audio");
291 This->dsp_bu = 1;
292 return;
293 }
294
295 out->p += len;
296 if (out->p == out->end)
297 {
298 long long duration;
299 long elapsed;
300
301 gettimeofday(&tv, NULL);
302 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
303 elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
304
305 if (elapsed >= (duration * 85) / 100)
306 {
307 rdpsnd_send_completion(packet->tick, packet->index);
308 free(out->data);
309 queue_lo = (queue_lo + 1) % MAX_QUEUE;
310 started = False;
311 }
312 else
313 {
314 This->dsp_bu = 1;
315 return;
316 }
317 }
318 }
319}
#define write
Definition: acwin.h:97
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
#define free
Definition: debug_ros.c:5
#define EWOULDBLOCK
Definition: errno.h:42
unsigned int BOOL
Definition: ntddk_ex.h:94
GLenum GLsizei len
Definition: glext.h:6722
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
static unsigned int queue_lo
Definition: rdpsnd_oss.c:52
static short g_samplewidth
Definition: rdpsnd_oss.c:43
static unsigned int queue_hi
Definition: rdpsnd_oss.c:52
#define MAX_QUEUE
Definition: rdpsnd_oss.c:38
static int g_snd_rate
Definition: rdpsnd_oss.c:42
static struct audio_packet packet_queue[MAX_QUEUE]
static BOOL g_driver_broken
Definition: rdpsnd_oss.c:44
static FILE * out
Definition: regtests2xml.c:44
int ssize_t
Definition: rosdhcp.h:48
#define errno
Definition: errno.h:18
#define memset(x, y, z)
Definition: compat.h:39
Definition: dhcpd.h:135
Definition: parse.h:23
#define ioctl
Definition: wintirpc.h:60

Referenced by wave_out_write().

◆ wave_out_set_format()

BOOL wave_out_set_format ( WAVEFORMATEX pwfx)

Definition at line 95 of file rdpsnd_oss.c.

96{
97 int stereo, format, fragments;
98
99 ioctl(This->dsp_, SNDCTL_DSP_RESET, NULL);
100 ioctl(This->dsp_, SNDCTL_DSP_SYNC, NULL);
101
102 if (pwfx->wBitsPerSample == 8)
103 format = AFMT_U8;
104 else if (pwfx->wBitsPerSample == 16)
105 format = AFMT_S16_LE;
106
107 g_samplewidth = pwfx->wBitsPerSample / 8;
108
109 if (ioctl(This->dsp_, SNDCTL_DSP_SETFMT, &format) == -1)
110 {
111 perror("SNDCTL_DSP_SETFMT");
112 close(This->dsp_);
113 return False;
114 }
115
116 if (pwfx->nChannels == 2)
117 {
118 stereo = 1;
119 g_samplewidth *= 2;
120 }
121 else
122 {
123 stereo = 0;
124 }
125
126 if (ioctl(This->dsp_, SNDCTL_DSP_STEREO, &stereo) == -1)
127 {
128 perror("SNDCTL_DSP_CHANNELS");
129 close(This->dsp_);
130 return False;
131 }
132
134 if (ioctl(This->dsp_, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
135 {
136 perror("SNDCTL_DSP_SPEED");
137 close(This->dsp_);
138 return False;
139 }
140
141 /* try to get 7 fragments of 2^12 bytes size */
142 fragments = (7 << 16) + 12;
143 ioctl(This->dsp_, SNDCTL_DSP_SETFRAGMENT, &fragments);
144
145 if (!g_driver_broken)
146 {
147 audio_buf_info info;
148
149 memset(&info, 0, sizeof(info));
150 if (ioctl(This->dsp_, SNDCTL_DSP_GETOSPACE, &info) == -1)
151 {
152 perror("SNDCTL_DSP_GETOSPACE");
153 close(This->dsp_);
154 return False;
155 }
156
157 if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
158 {
160 "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
161 info.fragments, info.fragstotal, info.fragsize);
163 }
164 }
165
166 return True;
167}
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
DWORD nSamplesPerSec
Definition: audioclient.idl:42

◆ wave_out_volume()

void wave_out_volume ( uint16  left,
uint16  right 
)

Definition at line 170 of file rdpsnd_oss.c.

171{
172 static BOOL use_dev_mixer = False;
174 int fd_mix = -1;
175
176 volume = left / (65536 / 100);
177 volume |= right / (65536 / 100) << 8;
178
179 if (use_dev_mixer)
180 {
181 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
182 {
183 perror("open /dev/mixer");
184 return;
185 }
186
187 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
188 {
189 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
190 return;
191 }
192
193 close(fd_mix);
194 }
195
196 if (ioctl(This->dsp_, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
197 {
198 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
199 use_dev_mixer = True;
200 return;
201 }
202}
unsigned int uint32
Definition: types.h:32
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
#define O_RDWR
Definition: fcntl.h:36

◆ wave_out_write()

void wave_out_write ( STREAM  s,
uint16  tick,
uint8  index 
)

Definition at line 205 of file rdpsnd_oss.c.

206{
208 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
209
210 if (next_hi == queue_lo)
211 {
212 error("No space to queue audio packet\n");
213 return;
214 }
215
216 queue_hi = next_hi;
217
218 packet->s = *s;
219 packet->tick = tick;
220 packet->index = index;
221 packet->s.p += 4;
222
223 /* we steal the data buffer from s, give it a new one */
224 s->data = (uint8 *) malloc(s->size);
225
226 if (!This->dsp_bu)
228}
unsigned char uint8
Definition: types.h:28
#define index(s, c)
Definition: various.h:29
#define malloc
Definition: debug_ros.c:4
GLdouble s
Definition: gl.h:2039
#define error(str)
Definition: mkdosfs.c:1605
void wave_out_play(void)
Definition: rdpsnd_oss.c:231

Variable Documentation

◆ dsp_

int This dsp_

Definition at line 40 of file rdpsnd_oss.c.

◆ dsp_bu

BOOL This dsp_bu = False

Definition at line 41 of file rdpsnd_oss.c.

◆ g_driver_broken

BOOL g_driver_broken = False
static

Definition at line 44 of file rdpsnd_oss.c.

Referenced by wave_out_play(), and wave_out_set_format().

◆ g_samplewidth

short g_samplewidth
static

Definition at line 43 of file rdpsnd_oss.c.

Referenced by wave_out_play(), and wave_out_set_format().

◆ g_snd_rate

int g_snd_rate
static

Definition at line 42 of file rdpsnd_oss.c.

Referenced by wave_out_play(), and wave_out_set_format().

◆ packet_queue

struct audio_packet packet_queue[MAX_QUEUE]
static

Referenced by wave_out_play(), and wave_out_write().

◆ queue_hi

unsigned int queue_hi
static

Definition at line 52 of file rdpsnd_oss.c.

Referenced by wave_out_play(), and wave_out_write().

◆ queue_lo

unsigned int queue_lo
static

Definition at line 52 of file rdpsnd_oss.c.

Referenced by wave_out_play(), and wave_out_write().