/[rdesktop]/jpeg/rdesktop/trunk/rdpsnd_oss.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/rdpsnd_oss.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 499 by astrand, Wed Oct 15 14:01:32 2003 UTC revision 1227 by astrand, Thu Apr 13 07:37:24 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions - Open Sound System     Sound Channel Process Functions - Open Sound System
4     Copyright (C) Matthew Chapman 2003     Copyright (C) Matthew Chapman 2003
# Line 19  Line 19 
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */  */
21    
22    /*
23       This is a workaround for Esound bug 312665.
24       FIXME: Remove this when Esound is fixed.
25    */
26    #ifdef _FILE_OFFSET_BITS
27    #undef _FILE_OFFSET_BITS
28    #endif
29    
30  #include "rdesktop.h"  #include "rdesktop.h"
31  #include <unistd.h>  #include <unistd.h>
32  #include <fcntl.h>  #include <fcntl.h>
33  #include <errno.h>  #include <errno.h>
34    #include <sys/time.h>
35  #include <sys/ioctl.h>  #include <sys/ioctl.h>
36  #include <sys/soundcard.h>  #include <sys/soundcard.h>
37    
38  #define MAX_QUEUE       10  #define MAX_QUEUE       10
39    
40  int g_dsp_fd;  int g_dsp_fd;
41  BOOL g_dsp_busy;  BOOL g_dsp_busy = False;
42    static int g_snd_rate;
43    static short g_samplewidth;
44    static BOOL g_driver_broken = False;
45    
46  static struct audio_packet  static struct audio_packet
47  {  {
# Line 42  static unsigned int queue_hi, queue_lo; Line 54  static unsigned int queue_hi, queue_lo;
54  BOOL  BOOL
55  wave_out_open(void)  wave_out_open(void)
56  {  {
57          char *dsp_dev = "/dev/dsp";          char *dsp_dev = getenv("AUDIODEV");
58    
59            if (dsp_dev == NULL)
60            {
61                    dsp_dev = xstrdup("/dev/dsp");
62            }
63    
64          if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)          if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
65          {          {
# Line 77  wave_out_format_supported(WAVEFORMATEX * Line 94  wave_out_format_supported(WAVEFORMATEX *
94  BOOL  BOOL
95  wave_out_set_format(WAVEFORMATEX * pwfx)  wave_out_set_format(WAVEFORMATEX * pwfx)
96  {  {
97          int speed, channels, format;          int stereo, format, fragments;
98    
99          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
100          ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);          ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
# Line 87  wave_out_set_format(WAVEFORMATEX * pwfx) Line 104  wave_out_set_format(WAVEFORMATEX * pwfx)
104          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
105                  format = AFMT_S16_LE;                  format = AFMT_S16_LE;
106    
107            g_samplewidth = pwfx->wBitsPerSample / 8;
108    
109          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
110          {          {
111                  perror("SNDCTL_DSP_SETFMT");                  perror("SNDCTL_DSP_SETFMT");
# Line 94  wave_out_set_format(WAVEFORMATEX * pwfx) Line 113  wave_out_set_format(WAVEFORMATEX * pwfx)
113                  return False;                  return False;
114          }          }
115    
116          channels = pwfx->nChannels;          if (pwfx->nChannels == 2)
117          if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)          {
118                    stereo = 1;
119                    g_samplewidth *= 2;
120            }
121            else
122            {
123                    stereo = 0;
124            }
125    
126            if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
127          {          {
128                  perror("SNDCTL_DSP_CHANNELS");                  perror("SNDCTL_DSP_CHANNELS");
129                  close(g_dsp_fd);                  close(g_dsp_fd);
130                  return False;                  return False;
131          }          }
132    
133          speed = pwfx->nSamplesPerSec;          g_snd_rate = pwfx->nSamplesPerSec;
134          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &speed) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
135          {          {
136                  perror("SNDCTL_DSP_SPEED");                  perror("SNDCTL_DSP_SPEED");
137                  close(g_dsp_fd);                  close(g_dsp_fd);
138                  return False;                  return False;
139          }          }
140    
141            /* try to get 7 fragments of 2^12 bytes size */
142            fragments = (7 << 16) + 12;
143            ioctl(g_dsp_fd, 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(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
151                    {
152                            perror("SNDCTL_DSP_GETOSPACE");
153                            close(g_dsp_fd);
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);
162                            g_driver_broken = True;
163                    }
164            }
165    
166          return True;          return True;
167  }  }
168    
169  void  void
170  wave_out_volume(uint16 left, uint16 right)  wave_out_volume(uint16 left, uint16 right)
171  {  {
172            static BOOL use_dev_mixer = False;
173          uint32 volume;          uint32 volume;
174            int fd_mix = -1;
175    
176          volume = left / (65536 / 100);          volume = left / (65536 / 100);
177          volume |= right / (65536 / 100) << 8;          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(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)          if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
197          {          {
198                  perror("MIXER_WRITE(SOUND_MIXER_PCM)");                  perror("MIXER_WRITE(SOUND_MIXER_PCM)");
199                    use_dev_mixer = True;
200                  return;                  return;
201          }          }
202  }  }
# Line 147  wave_out_write(STREAM s, uint16 tick, ui Line 221  wave_out_write(STREAM s, uint16 tick, ui
221          packet->s.p += 4;          packet->s.p += 4;
222    
223          /* we steal the data buffer from s, give it a new one */          /* we steal the data buffer from s, give it a new one */
224          s->data = malloc(s->size);          s->data = (uint8 *) malloc(s->size);
225    
226          if (!g_dsp_busy)          if (!g_dsp_busy)
227                  wave_out_play();                  wave_out_play();
# Line 159  wave_out_play(void) Line 233  wave_out_play(void)
233          struct audio_packet *packet;          struct audio_packet *packet;
234          ssize_t len;          ssize_t len;
235          STREAM out;          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)          while (1)
243          {          {
# Line 171  wave_out_play(void) Line 250  wave_out_play(void)
250                  packet = &packet_queue[queue_lo];                  packet = &packet_queue[queue_lo];
251                  out = &packet->s;                  out = &packet->s;
252    
253                  len = write(g_dsp_fd, out->p, out->end - out->p);                  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(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
267                            {
268                                    perror("SNDCTL_DSP_GETOSPACE");
269                                    return;
270                            }
271    
272                            if (info.fragments == 0)
273                            {
274                                    g_dsp_busy = 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(g_dsp_fd, out->p, len);
287                  if (len == -1)                  if (len == -1)
288                  {                  {
289                          if (errno != EWOULDBLOCK)                          if (errno != EWOULDBLOCK)
# Line 183  wave_out_play(void) Line 295  wave_out_play(void)
295                  out->p += len;                  out->p += len;
296                  if (out->p == out->end)                  if (out->p == out->end)
297                  {                  {
298                          rdpsnd_send_completion(packet->tick, packet->index);                          long long duration;
299                          free(out->data);                          long elapsed;
300                          queue_lo = (queue_lo + 1) % MAX_QUEUE;  
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                                    g_dsp_busy = 1;
315                                    return;
316                            }
317                  }                  }
318          }          }
   
319  }  }

Legend:
Removed from v.499  
changed lines
  Added in v.1227

  ViewVC Help
Powered by ViewVC 1.1.26