/[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 1247 by stargo, Wed Jul 12 09:57:05 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_LEN         512
39  #define MAX_QUEUE       10  #define MAX_QUEUE       10
40    
41  int g_dsp_fd;  int g_dsp_fd;
42  BOOL g_dsp_busy;  BOOL g_dsp_busy = False;
43    static int snd_rate;
44    static short samplewidth;
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 ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)          if (dsp_dev == NULL)
60            {
61                    dsp_dev = xstrdup("/dev/dsp");
62            }
63    
64            if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
65          {          {
66                  perror(dsp_dev);                  perror(dsp_dev);
67                  return False;                  return False;
68          }          }
69    
         /* Non-blocking so that user interface is responsive */  
         fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);  
70          return True;          return True;
71  }  }
72    
# Line 77  wave_out_format_supported(WAVEFORMATEX * Line 92  wave_out_format_supported(WAVEFORMATEX *
92  BOOL  BOOL
93  wave_out_set_format(WAVEFORMATEX * pwfx)  wave_out_set_format(WAVEFORMATEX * pwfx)
94  {  {
95          int speed, channels, format;          int stereo, format, fragments;
96            static BOOL driver_broken = False;
97    
98          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
99          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 103  wave_out_set_format(WAVEFORMATEX * pwfx)
103          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
104                  format = AFMT_S16_LE;                  format = AFMT_S16_LE;
105    
106            samplewidth = pwfx->wBitsPerSample / 8;
107    
108          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
109          {          {
110                  perror("SNDCTL_DSP_SETFMT");                  perror("SNDCTL_DSP_SETFMT");
# Line 94  wave_out_set_format(WAVEFORMATEX * pwfx) Line 112  wave_out_set_format(WAVEFORMATEX * pwfx)
112                  return False;                  return False;
113          }          }
114    
115          channels = pwfx->nChannels;          if (pwfx->nChannels == 2)
116          if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)          {
117                    stereo = 1;
118                    samplewidth *= 2;
119            }
120            else
121            {
122                    stereo = 0;
123            }
124    
125            if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
126          {          {
127                  perror("SNDCTL_DSP_CHANNELS");                  perror("SNDCTL_DSP_CHANNELS");
128                  close(g_dsp_fd);                  close(g_dsp_fd);
129                  return False;                  return False;
130          }          }
131    
132          speed = pwfx->nSamplesPerSec;          snd_rate = pwfx->nSamplesPerSec;
133          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &speed) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
134          {          {
135                  perror("SNDCTL_DSP_SPEED");                  perror("SNDCTL_DSP_SPEED");
136                  close(g_dsp_fd);                  close(g_dsp_fd);
137                  return False;                  return False;
138          }          }
139    
140            /* try to get 12 fragments of 2^12 bytes size */
141            fragments = (12 << 16) + 12;
142            ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
143    
144            if (!driver_broken)
145            {
146                    audio_buf_info info;
147    
148                    memset(&info, 0, sizeof(info));
149                    if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
150                    {
151                            perror("SNDCTL_DSP_GETOSPACE");
152                            close(g_dsp_fd);
153                            return False;
154                    }
155    
156                    if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
157                    {
158                            fprintf(stderr,
159                                    "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
160                                    info.fragments, info.fragstotal, info.fragsize);
161                            driver_broken = True;
162                    }
163            }
164    
165          return True;          return True;
166  }  }
167    
168  void  void
169  wave_out_volume(uint16 left, uint16 right)  wave_out_volume(uint16 left, uint16 right)
170  {  {
171            static BOOL use_dev_mixer = False;
172          uint32 volume;          uint32 volume;
173            int fd_mix = -1;
174    
175          volume = left / (65536 / 100);          volume = left / (65536 / 100);
176          volume |= right / (65536 / 100) << 8;          volume |= right / (65536 / 100) << 8;
177    
178            if (use_dev_mixer)
179            {
180                    if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
181                    {
182                            perror("open /dev/mixer");
183                            return;
184                    }
185    
186                    if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
187                    {
188                            perror("MIXER_WRITE(SOUND_MIXER_PCM)");
189                            return;
190                    }
191    
192                    close(fd_mix);
193            }
194    
195          if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)          if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
196          {          {
197                  perror("MIXER_WRITE(SOUND_MIXER_PCM)");                  perror("MIXER_WRITE(SOUND_MIXER_PCM)");
198                    use_dev_mixer = True;
199                  return;                  return;
200          }          }
201  }  }
# Line 147  wave_out_write(STREAM s, uint16 tick, ui Line 220  wave_out_write(STREAM s, uint16 tick, ui
220          packet->s.p += 4;          packet->s.p += 4;
221    
222          /* we steal the data buffer from s, give it a new one */          /* we steal the data buffer from s, give it a new one */
223          s->data = malloc(s->size);          s->data = (uint8 *) malloc(s->size);
224    
225          if (!g_dsp_busy)          if (!g_dsp_busy)
226                  wave_out_play();                  wave_out_play();
# Line 159  wave_out_play(void) Line 232  wave_out_play(void)
232          struct audio_packet *packet;          struct audio_packet *packet;
233          ssize_t len;          ssize_t len;
234          STREAM out;          STREAM out;
235            static long startedat_us;
236            static long startedat_s;
237            static BOOL started = False;
238            struct timeval tv;
239    
240          while (1)          if (queue_lo == queue_hi)
241          {          {
242                  if (queue_lo == queue_hi)                  g_dsp_busy = 0;
243                  {                  return;
244                          g_dsp_busy = 0;          }
                         return;  
                 }  
245    
246                  packet = &packet_queue[queue_lo];          packet = &packet_queue[queue_lo];
247                  out = &packet->s;          out = &packet->s;
248    
249                  len = write(g_dsp_fd, out->p, out->end - out->p);          if (!started)
250                  if (len == -1)          {
251                  {                  gettimeofday(&tv, NULL);
252                          if (errno != EWOULDBLOCK)                  startedat_us = tv.tv_usec;
253                                  perror("write audio");                  startedat_s = tv.tv_sec;
254                          g_dsp_busy = 1;                  started = True;
255                          return;          }
256                  }  
257            len = out->end - out->p;
258    
259            len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
260            if (len == -1)
261            {
262                    if (errno != EWOULDBLOCK)
263                            perror("write audio");
264                    g_dsp_busy = 1;
265                    return;
266            }
267    
268            out->p += len;
269            if (out->p == out->end)
270            {
271                    long long duration;
272                    long elapsed;
273    
274                    gettimeofday(&tv, NULL);
275                    duration = (out->size * (1000000 / (samplewidth * snd_rate)));
276                    elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
277    
278                  out->p += len;                  if (elapsed >= (duration * 85) / 100)
                 if (out->p == out->end)  
279                  {                  {
280                          rdpsnd_send_completion(packet->tick, packet->index);                          rdpsnd_send_completion(packet->tick, packet->index);
281                          free(out->data);                          free(out->data);
282                          queue_lo = (queue_lo + 1) % MAX_QUEUE;                          queue_lo = (queue_lo + 1) % MAX_QUEUE;
283                            started = False;
284                    }
285                    else
286                    {
287                            g_dsp_busy = 1;
288                            return;
289                  }                  }
290          }          }
291            g_dsp_busy = 1;
292            return;
293  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26