/[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 1260 by stargo, Sun Sep 17 15:25:10 2006 UTC revision 1318 by astrand, Thu Nov 2 11:55:59 2006 UTC
# Line 29  Line 29 
29    
30  #include "rdesktop.h"  #include "rdesktop.h"
31  #include "rdpsnd.h"  #include "rdpsnd.h"
32    #include "rdpsnd_dsp.h"
33  #include <unistd.h>  #include <unistd.h>
34  #include <fcntl.h>  #include <fcntl.h>
35  #include <errno.h>  #include <errno.h>
36    #include <unistd.h>
37  #include <sys/time.h>  #include <sys/time.h>
38  #include <sys/ioctl.h>  #include <sys/ioctl.h>
39  #include <sys/soundcard.h>  #include <sys/soundcard.h>
40    #include <sys/types.h>
41    #include <sys/stat.h>
42    
43  #define DEFAULTDEVICE   "/dev/dsp"  #define DEFAULTDEVICE   "/dev/dsp"
44  #define MAX_LEN         512  #define MAX_LEN         512
# Line 42  Line 46 
46  static int snd_rate;  static int snd_rate;
47  static short samplewidth;  static short samplewidth;
48  static char *dsp_dev;  static char *dsp_dev;
49    static struct audio_driver oss_driver;
50    static BOOL in_esddsp;
51    
52    static BOOL
53    detect_esddsp(void)
54    {
55            struct stat s;
56            char *preload;
57    
58            if (fstat(g_dsp_fd, &s) == -1)
59                    return False;
60    
61            if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
62                    return False;
63    
64            preload = getenv("LD_PRELOAD");
65            if (preload == NULL)
66                    return False;
67    
68            if (strstr(preload, "esddsp") == NULL)
69                    return False;
70    
71            return True;
72    }
73    
74  BOOL  BOOL
75  oss_open(void)  oss_open(void)
# Line 52  oss_open(void) Line 80  oss_open(void)
80                  return False;                  return False;
81          }          }
82    
83            in_esddsp = detect_esddsp();
84    
85          return True;          return True;
86  }  }
87    
# Line 59  void Line 89  void
89  oss_close(void)  oss_close(void)
90  {  {
91          close(g_dsp_fd);          close(g_dsp_fd);
92            g_dsp_busy = 0;
93  }  }
94    
95  BOOL  BOOL
# Line 93  oss_set_format(WAVEFORMATEX * pwfx) Line 124  oss_set_format(WAVEFORMATEX * pwfx)
124          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
125          {          {
126                  perror("SNDCTL_DSP_SETFMT");                  perror("SNDCTL_DSP_SETFMT");
127                  close(g_dsp_fd);                  oss_close();
128                  return False;                  return False;
129          }          }
130    
# Line 110  oss_set_format(WAVEFORMATEX * pwfx) Line 141  oss_set_format(WAVEFORMATEX * pwfx)
141          if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
142          {          {
143                  perror("SNDCTL_DSP_CHANNELS");                  perror("SNDCTL_DSP_CHANNELS");
144                  close(g_dsp_fd);                  oss_close();
145                  return False;                  return False;
146          }          }
147    
148            oss_driver.need_resampling = 0;
149          snd_rate = pwfx->nSamplesPerSec;          snd_rate = pwfx->nSamplesPerSec;
150          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
151          {          {
152                  perror("SNDCTL_DSP_SPEED");                  int rates[] = { 44100, 48000, 0 };
153                  close(g_dsp_fd);                  int *prates = rates;
154                  return False;  
155                    while (*prates != 0)
156                    {
157                            if ((pwfx->nSamplesPerSec != *prates)
158                                && (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
159                            {
160                                    oss_driver.need_resampling = 1;
161                                    snd_rate = *prates;
162                                    if (rdpsnd_dsp_resample_set
163                                        (snd_rate, pwfx->wBitsPerSample, pwfx->nChannels) == False)
164                                    {
165                                            error("rdpsnd_dsp_resample_set failed");
166                                            oss_close();
167                                            return False;
168                                    }
169    
170                                    break;
171                            }
172                            prates++;
173                    }
174    
175                    if (*prates == 0)
176                    {
177                            perror("SNDCTL_DSP_SPEED");
178                            oss_close();
179                            return False;
180                    }
181          }          }
182    
183          /* try to get 12 fragments of 2^12 bytes size */          /* try to get 12 fragments of 2^12 bytes size */
# Line 134  oss_set_format(WAVEFORMATEX * pwfx) Line 192  oss_set_format(WAVEFORMATEX * pwfx)
192                  if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)                  if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
193                  {                  {
194                          perror("SNDCTL_DSP_GETOSPACE");                          perror("SNDCTL_DSP_GETOSPACE");
195                          close(g_dsp_fd);                          oss_close();
196                          return False;                          return False;
197                  }                  }
198    
# Line 153  oss_set_format(WAVEFORMATEX * pwfx) Line 211  oss_set_format(WAVEFORMATEX * pwfx)
211  void  void
212  oss_volume(uint16 left, uint16 right)  oss_volume(uint16 left, uint16 right)
213  {  {
         static BOOL use_dev_mixer = False;  
214          uint32 volume;          uint32 volume;
         int fd_mix = -1;  
215    
216          volume = left / (65536 / 100);          volume = left / (65536 / 100);
217          volume |= right / (65536 / 100) << 8;          volume |= right / (65536 / 100) << 8;
218    
         if (use_dev_mixer)  
         {  
                 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)  
                 {  
                         perror("open /dev/mixer");  
                         return;  
                 }  
   
                 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)  
                 {  
                         perror("MIXER_WRITE(SOUND_MIXER_PCM)");  
                         return;  
                 }  
   
                 close(fd_mix);  
         }  
   
219          if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)          if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
220          {          {
221                  perror("MIXER_WRITE(SOUND_MIXER_PCM)");                  warning("hardware volume control unavailable, falling back to software volume control!\n");
222                  use_dev_mixer = True;                  oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
223                    rdpsnd_dsp_softvol_set(left, right);
224                  return;                  return;
225          }          }
226  }  }
# Line 191  oss_play(void) Line 231  oss_play(void)
231          struct audio_packet *packet;          struct audio_packet *packet;
232          ssize_t len;          ssize_t len;
233          STREAM out;          STREAM out;
         static long startedat_us;  
         static long startedat_s;  
         static BOOL started = False;  
         struct timeval tv;  
234    
235          if (rdpsnd_queue_empty())          if (rdpsnd_queue_empty())
236          {          {
# Line 205  oss_play(void) Line 241  oss_play(void)
241          packet = rdpsnd_queue_current_packet();          packet = rdpsnd_queue_current_packet();
242          out = &packet->s;          out = &packet->s;
243    
         if (!started)  
         {  
                 gettimeofday(&tv, NULL);  
                 startedat_us = tv.tv_usec;  
                 startedat_s = tv.tv_sec;  
                 started = True;  
         }  
   
244          len = out->end - out->p;          len = out->end - out->p;
245    
246          len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);          len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
# Line 225  oss_play(void) Line 253  oss_play(void)
253          }          }
254    
255          out->p += len;          out->p += len;
256    
257          if (out->p == out->end)          if (out->p == out->end)
258          {          {
259                  long long duration;                  int delay_bytes;
260                  long elapsed;                  unsigned long delay_us;
261                    audio_buf_info info;
262    
263                  gettimeofday(&tv, NULL);                  if (in_esddsp)
264                  duration = (out->size * (1000000 / (samplewidth * snd_rate)));                  {
265                  elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);                          /* EsounD has no way of querying buffer status, so we have to
266                             * go with a fixed size. */
267                  if (elapsed >= (duration * 85) / 100)                          delay_bytes = out->size;
                 {  
                         /* We need to add 50 to tell windows that time has passed while  
                          * playing this packet */  
                         rdpsnd_send_completion(packet->tick + 50, packet->index);  
                         rdpsnd_queue_next();  
                         started = False;  
268                  }                  }
269                  else                  else
270                  {                  {
271                          g_dsp_busy = 1;  #ifdef SNDCTL_DSP_GETODELAY
272                          return;                          delay_bytes = 0;
273                            if (ioctl(g_dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
274                                    delay_bytes = -1;
275    #else
276                            delay_bytes = -1;
277    #endif
278    
279                            if (delay_bytes == -1)
280                            {
281                                    if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
282                                            delay_bytes = info.fragstotal * info.fragsize - info.bytes;
283                                    else
284                                            delay_bytes = out->size;
285                            }
286                  }                  }
287    
288                    delay_us = delay_bytes * (1000000 / (samplewidth * snd_rate));
289                    rdpsnd_queue_next(delay_us);
290          }          }
291          g_dsp_busy = 1;          else
292            {
293                    g_dsp_busy = 1;
294            }
295    
296          return;          return;
297  }  }
298    
299  struct audio_driver *  struct audio_driver *
300  oss_register(char *options)  oss_register(char *options)
301  {  {
         static struct audio_driver oss_driver;  
   
         oss_driver.wave_out_write = rdpsnd_queue_write;  
302          oss_driver.wave_out_open = oss_open;          oss_driver.wave_out_open = oss_open;
303          oss_driver.wave_out_close = oss_close;          oss_driver.wave_out_close = oss_close;
304          oss_driver.wave_out_format_supported = oss_format_supported;          oss_driver.wave_out_format_supported = oss_format_supported;
# Line 268  oss_register(char *options) Line 309  oss_register(char *options)
309          oss_driver.description =          oss_driver.description =
310                  xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV");                  xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV");
311          oss_driver.need_byteswap_on_be = 0;          oss_driver.need_byteswap_on_be = 0;
312            oss_driver.need_resampling = 0;
313          oss_driver.next = NULL;          oss_driver.next = NULL;
314    
315          if (options)          if (options)

Legend:
Removed from v.1260  
changed lines
  Added in v.1318

  ViewVC Help
Powered by ViewVC 1.1.26