ReactOS  0.4.14-dev-115-g4576127
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
WORD wBitsPerSample
Definition: audioclient.idl:45
#define True
Definition: types.h:24
#define False
Definition: types.h:25

◆ 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 open
Definition: acwin.h:95
#define O_NONBLOCK
Definition: port.h:158
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
#define O_WRONLY
Definition: acwin.h:111
smooth NULL
Definition: ftsmooth.c:416
#define True
Definition: types.h:24
#define False
Definition: types.h:25
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
char * xstrdup(const char *s)
Definition: uimain.c:768

◆ 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 }
UCHAR packet[_PAGE_SIZE]
Definition: serial.c:53
static unsigned int queue_lo
Definition: rdpsnd_oss.c:52
#define free
Definition: debug_ros.c:5
static int g_snd_rate
Definition: rdpsnd_oss.c:42
int errno
struct _test_info info[]
Definition: SetCursorPos.c:19
#define write
Definition: acwin.h:97
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ioctl
Definition: wintirpc.h:60
#define EWOULDBLOCK
Definition: errno.h:42
smooth NULL
Definition: ftsmooth.c:416
Definition: dhcpd.h:135
#define True
Definition: types.h:24
#define False
Definition: types.h:25
static FILE * out
Definition: regtests2xml.c:44
static BOOL g_driver_broken
Definition: rdpsnd_oss.c:44
#define MAX_QUEUE
Definition: rdpsnd_oss.c:38
Definition: parse.h:22
GLenum GLsizei len
Definition: glext.h:6722
int ssize_t
Definition: rosdhcp.h:48
static unsigned int queue_hi
Definition: rdpsnd_oss.c:52
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
static short g_samplewidth
Definition: rdpsnd_oss.c:43
static struct audio_packet packet_queue[MAX_QUEUE]
#define memset(x, y, z)
Definition: compat.h:39

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 
133  g_snd_rate = pwfx->nSamplesPerSec;
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  {
159  fprintf(stderr,
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 }
static int g_snd_rate
Definition: rdpsnd_oss.c:42
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
struct _test_info info[]
Definition: SetCursorPos.c:19
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define ioctl
Definition: wintirpc.h:60
WORD wBitsPerSample
Definition: audioclient.idl:45
smooth NULL
Definition: ftsmooth.c:416
DWORD nSamplesPerSec
Definition: audioclient.idl:42
#define True
Definition: types.h:24
#define False
Definition: types.h:25
static BOOL g_driver_broken
Definition: rdpsnd_oss.c:44
#define close
Definition: acwin.h:98
static short g_samplewidth
Definition: rdpsnd_oss.c:43
FILE * stderr
#define memset(x, y, z)
Definition: compat.h:39

◆ 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;
173  uint32 volume;
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 }
#define open
Definition: acwin.h:95
unsigned int uint32
Definition: types.h:32
#define O_NONBLOCK
Definition: port.h:158
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ioctl
Definition: wintirpc.h:60
#define True
Definition: types.h:24
#define False
Definition: types.h:25
GLint left
Definition: glext.h:7726
GLdouble GLdouble right
Definition: glext.h:10859
#define close
Definition: acwin.h:98
#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)
227  wave_out_play();
228 }
#define error(str)
Definition: mkdosfs.c:1605
static unsigned int queue_lo
Definition: rdpsnd_oss.c:52
void wave_out_play(void)
Definition: rdpsnd_oss.c:231
Definition: dhcpd.h:135
unsigned char uint8
Definition: types.h:28
#define index(s, c)
Definition: various.h:29
#define MAX_QUEUE
Definition: rdpsnd_oss.c:38
GLdouble s
Definition: gl.h:2039
static unsigned int queue_hi
Definition: rdpsnd_oss.c:52
#define malloc
Definition: debug_ros.c:4
static struct audio_packet packet_queue[MAX_QUEUE]
char data[MTU]
Definition: ipreceive.c:8

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().