/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdpsnd_oss.c

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

revision 475 by matthewc, Wed Oct 1 12:35:17 2003 UTC revision 761 by stargo, Fri Sep 3 22:35:08 2004 UTC
# Line 23  Line 23 
23  #include <unistd.h>  #include <unistd.h>
24  #include <fcntl.h>  #include <fcntl.h>
25  #include <errno.h>  #include <errno.h>
26    #include <sys/time.h>
27  #include <sys/ioctl.h>  #include <sys/ioctl.h>
28  #include <sys/soundcard.h>  #include <sys/soundcard.h>
29    
30  #define MAX_QUEUE       10  #define MAX_QUEUE       10
31    
32  int g_dsp_fd;  int g_dsp_fd;
33  BOOL g_dsp_busy;  BOOL g_dsp_busy = False;
34    static int g_snd_rate;
35    static short g_samplewidth;
36    static BOOL g_driver_broken = False;
37    
38  static struct audio_packet {  static struct audio_packet
39    {
40          struct stream s;          struct stream s;
41          uint16 tick;          uint16 tick;
42          uint8 index;          uint8 index;
# Line 41  static unsigned int queue_hi, queue_lo; Line 46  static unsigned int queue_hi, queue_lo;
46  BOOL  BOOL
47  wave_out_open(void)  wave_out_open(void)
48  {  {
49          char *dsp_dev = "/dev/dsp";          char *dsp_dev = getenv("AUDIODEV");
50    
51            if (dsp_dev == NULL)
52            {
53                    dsp_dev = "/dev/dsp";
54            }
55    
56          if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)          if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
57          {          {
58                  perror(dsp_dev);                  perror(dsp_dev);
59                  return False;                  return False;
60          }          }
61    
62          /* Non-blocking so that user interface is responsive */          /* Non-blocking so that user interface is responsive */
63          fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL)|O_NONBLOCK);          fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
64          return True;          return True;
65  }  }
66    
# Line 61  wave_out_close(void) Line 71  wave_out_close(void)
71  }  }
72    
73  BOOL  BOOL
74  wave_out_format_supported(WAVEFORMATEX *pwfx)  wave_out_format_supported(WAVEFORMATEX * pwfx)
75  {  {
76          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
77                  return False;                  return False;
# Line 74  wave_out_format_supported(WAVEFORMATEX * Line 84  wave_out_format_supported(WAVEFORMATEX *
84  }  }
85    
86  BOOL  BOOL
87  wave_out_set_format(WAVEFORMATEX *pwfx)  wave_out_set_format(WAVEFORMATEX * pwfx)
88  {  {
89          int speed, channels, format;          int stereo, format, fragments;
90    
91          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);          ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
92          ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);          ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
# Line 86  wave_out_set_format(WAVEFORMATEX *pwfx) Line 96  wave_out_set_format(WAVEFORMATEX *pwfx)
96          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
97                  format = AFMT_S16_LE;                  format = AFMT_S16_LE;
98    
99            g_samplewidth = pwfx->wBitsPerSample / 8;
100    
101          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
102          {          {
103                  perror("SNDCTL_DSP_SETFMT");                  perror("SNDCTL_DSP_SETFMT");
# Line 93  wave_out_set_format(WAVEFORMATEX *pwfx) Line 105  wave_out_set_format(WAVEFORMATEX *pwfx)
105                  return False;                  return False;
106          }          }
107    
108          channels = pwfx->nChannels;          if (pwfx->nChannels == 2)
109          if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)          {
110                    stereo = 1;
111                    g_samplewidth *= 2;
112            }
113            else
114            {
115                    stereo = 0;
116            }
117    
118            if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
119          {          {
120                  perror("SNDCTL_DSP_CHANNELS");                  perror("SNDCTL_DSP_CHANNELS");
121                  close(g_dsp_fd);                  close(g_dsp_fd);
122                  return False;                  return False;
123          }          }
124    
125          speed = pwfx->nSamplesPerSec;          g_snd_rate = pwfx->nSamplesPerSec;
126          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &speed) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
127          {          {
128                  perror("SNDCTL_DSP_SPEED");                  perror("SNDCTL_DSP_SPEED");
129                  close(g_dsp_fd);                  close(g_dsp_fd);
130                  return False;                  return False;
131          }          }
132    
133            /* try to get 7 fragments of 2^12 bytes size */
134            fragments = (7 << 16) + 12;
135            ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
136    
137            if (!g_driver_broken)
138            {
139                    audio_buf_info info;
140    
141                    if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
142                    {
143                            perror("SNDCTL_DSP_GETOSPACE");
144                            close(g_dsp_fd);
145                            return False;
146                    }
147    
148                    if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
149                    {
150                            fprintf(stderr,
151                                    "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
152                                    info.fragments, info.fragstotal, info.fragsize);
153                            g_driver_broken = True;
154                    }
155            }
156    
157          return True;          return True;
158  }  }
159    
160  void  void
161    wave_out_volume(uint16 left, uint16 right)
162    {
163            static BOOL use_dev_mixer = False;
164            uint32 volume;
165            int fd_mix = -1;
166    
167            volume = left / (65536 / 100);
168            volume |= right / (65536 / 100) << 8;
169    
170            if (use_dev_mixer)
171            {
172                    if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
173                    {
174                            perror("open /dev/mixer");
175                            return;
176                    }
177    
178                    if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
179                    {
180                            perror("MIXER_WRITE(SOUND_MIXER_PCM)");
181                            return;
182                    }
183    
184                    close(fd_mix);
185            }
186    
187            if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
188            {
189                    perror("MIXER_WRITE(SOUND_MIXER_PCM)");
190                    use_dev_mixer = True;
191                    return;
192            }
193    }
194    
195    void
196  wave_out_write(STREAM s, uint16 tick, uint8 index)  wave_out_write(STREAM s, uint16 tick, uint8 index)
197  {  {
198          struct audio_packet *packet = &packet_queue[queue_lo];          struct audio_packet *packet = &packet_queue[queue_hi];
199          unsigned int next_hi = (queue_lo + 1) % MAX_QUEUE;          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
200    
201          if (next_hi == queue_lo)          if (next_hi == queue_lo)
202          {          {
# Line 129  wave_out_write(STREAM s, uint16 tick, ui Line 209  wave_out_write(STREAM s, uint16 tick, ui
209          packet->s = *s;          packet->s = *s;
210          packet->tick = tick;          packet->tick = tick;
211          packet->index = index;          packet->index = index;
212            packet->s.p += 4;
213    
214          /* we steal the data buffer from s, give it a new one */          /* we steal the data buffer from s, give it a new one */
215          s->data = malloc(s->size);          s->data = malloc(s->size);
# Line 143  wave_out_play(void) Line 224  wave_out_play(void)
224          struct audio_packet *packet;          struct audio_packet *packet;
225          ssize_t len;          ssize_t len;
226          STREAM out;          STREAM out;
227            static long startedat_us;
228            static long startedat_s;
229            static BOOL started = False;
230            struct timeval tv;
231            audio_buf_info info;
232    
233          while (1)          while (1)
234          {          {
# Line 155  wave_out_play(void) Line 241  wave_out_play(void)
241                  packet = &packet_queue[queue_lo];                  packet = &packet_queue[queue_lo];
242                  out = &packet->s;                  out = &packet->s;
243    
244                  len = write(g_dsp_fd, out->p, out->end-out->p);                  if (!started)
245                    {
246                            gettimeofday(&tv, NULL);
247                            startedat_us = tv.tv_usec;
248                            startedat_s = tv.tv_sec;
249                            started = True;
250                    }
251    
252                    len = out->end - out->p;
253    
254                    if (!g_driver_broken)
255                    {
256                            if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
257                            {
258                                    perror("SNDCTL_DSP_GETOSPACE");
259                                    return;
260                            }
261    
262                            if (info.fragments == 0)
263                            {
264                                    g_dsp_busy = 1;
265                                    return;
266                            }
267    
268                            if (info.fragments * info.fragsize < len
269                                && info.fragments * info.fragsize > 0)
270                            {
271                                    len = info.fragments * info.fragsize;
272                            }
273                    }
274    
275    
276                    len = write(g_dsp_fd, out->p, len);
277                  if (len == -1)                  if (len == -1)
278                  {                  {
279                          if (errno != EWOULDBLOCK)                          if (errno != EWOULDBLOCK)
# Line 167  wave_out_play(void) Line 285  wave_out_play(void)
285                  out->p += len;                  out->p += len;
286                  if (out->p == out->end)                  if (out->p == out->end)
287                  {                  {
288                          rdpsnd_send_completion(packet->tick, packet->index);                          long long duration;
289                          free(out->data);                          long elapsed;
290                          queue_lo = (queue_lo + 1) % MAX_QUEUE;  
291                            gettimeofday(&tv, NULL);
292                            duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
293                            elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
294    
295                            if (elapsed >= (duration * 85) / 100)
296                            {
297                                    rdpsnd_send_completion(packet->tick, packet->index);
298                                    free(out->data);
299                                    queue_lo = (queue_lo + 1) % MAX_QUEUE;
300                                    started = False;
301                            }
302                            else
303                            {
304                                    g_dsp_busy = 1;
305                                    return;
306                            }
307                  }                  }
308          }          }
   
309  }  }

Legend:
Removed from v.475  
changed lines
  Added in v.761

  ViewVC Help
Powered by ViewVC 1.1.26