/[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 1279 by stargo, Sun Oct 1 14:03:43 2006 UTC revision 1318 by astrand, Thu Nov 2 11:55:59 2006 UTC
# Line 33  Line 33 
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 44  static int snd_rate; Line 47  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;  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 54  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 61  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 95  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 112  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 136  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 175  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 189  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 209  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            else
292            {
293                    g_dsp_busy = 1;
294          }          }
295          g_dsp_busy = 1;  
296          return;          return;
297  }  }
298    
299  struct audio_driver *  struct audio_driver *
300  oss_register(char *options)  oss_register(char *options)
301  {  {
         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;

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

  ViewVC Help
Powered by ViewVC 1.1.26