/[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 1227 by astrand, Thu Apr 13 07:37:24 2006 UTC revision 1247 by stargo, Wed Jul 12 09:57:05 2006 UTC
# Line 35  Line 35 
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 = False;  BOOL g_dsp_busy = False;
43  static int g_snd_rate;  static int snd_rate;
44  static short g_samplewidth;  static short samplewidth;
 static BOOL g_driver_broken = False;  
45    
46  static struct audio_packet  static struct audio_packet
47  {  {
# Line 61  wave_out_open(void) Line 61  wave_out_open(void)
61                  dsp_dev = xstrdup("/dev/dsp");                  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)) == -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 95  BOOL Line 93  BOOL
93  wave_out_set_format(WAVEFORMATEX * pwfx)  wave_out_set_format(WAVEFORMATEX * pwfx)
94  {  {
95          int stereo, format, fragments;          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 104  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          g_samplewidth = pwfx->wBitsPerSample / 8;          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          {          {
# Line 116  wave_out_set_format(WAVEFORMATEX * pwfx) Line 115  wave_out_set_format(WAVEFORMATEX * pwfx)
115          if (pwfx->nChannels == 2)          if (pwfx->nChannels == 2)
116          {          {
117                  stereo = 1;                  stereo = 1;
118                  g_samplewidth *= 2;                  samplewidth *= 2;
119          }          }
120          else          else
121          {          {
# Line 130  wave_out_set_format(WAVEFORMATEX * pwfx) Line 129  wave_out_set_format(WAVEFORMATEX * pwfx)
129                  return False;                  return False;
130          }          }
131    
132          g_snd_rate = pwfx->nSamplesPerSec;          snd_rate = pwfx->nSamplesPerSec;
133          if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -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 7 fragments of 2^12 bytes size */          /* try to get 12 fragments of 2^12 bytes size */
141          fragments = (7 << 16) + 12;          fragments = (12 << 16) + 12;
142          ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);          ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
143    
144          if (!g_driver_broken)          if (!driver_broken)
145          {          {
146                  audio_buf_info info;                  audio_buf_info info;
147    
# Line 159  wave_out_set_format(WAVEFORMATEX * pwfx) Line 158  wave_out_set_format(WAVEFORMATEX * pwfx)
158                          fprintf(stderr,                          fprintf(stderr,
159                                  "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",                                  "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
160                                  info.fragments, info.fragstotal, info.fragsize);                                  info.fragments, info.fragstotal, info.fragsize);
161                          g_driver_broken = True;                          driver_broken = True;
162                  }                  }
163          }          }
164    
# Line 237  wave_out_play(void) Line 236  wave_out_play(void)
236          static long startedat_s;          static long startedat_s;
237          static BOOL started = False;          static BOOL started = False;
238          struct timeval tv;          struct timeval tv;
         audio_buf_info info;  
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                  if (!started)          if (!started)
250                  {          {
251                          gettimeofday(&tv, NULL);                  gettimeofday(&tv, NULL);
252                          startedat_us = tv.tv_usec;                  startedat_us = tv.tv_usec;
253                          startedat_s = tv.tv_sec;                  startedat_s = tv.tv_sec;
254                          started = True;                  started = True;
255                  }          }
256    
257                  len = out->end - out->p;          len = out->end - out->p;
258    
259                  if (!g_driver_broken)          len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
260                  {          if (len == -1)
261                          memset(&info, 0, sizeof(info));          {
262                          if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)                  if (errno != EWOULDBLOCK)
263                          {                          perror("write audio");
264                                  perror("SNDCTL_DSP_GETOSPACE");                  g_dsp_busy = 1;
265                                  return;                  return;
266                          }          }
   
                         if (info.fragments == 0)  
                         {  
                                 g_dsp_busy = 1;  
                                 return;  
                         }  
   
                         if (info.fragments * info.fragsize < len  
                             && info.fragments * info.fragsize > 0)  
                         {  
                                 len = info.fragments * info.fragsize;  
                         }  
                 }  
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                  len = write(g_dsp_fd, out->p, len);                  if (elapsed >= (duration * 85) / 100)
                 if (len == -1)  
279                  {                  {
280                          if (errno != EWOULDBLOCK)                          rdpsnd_send_completion(packet->tick, packet->index);
281                                  perror("write audio");                          free(out->data);
282                          g_dsp_busy = 1;                          queue_lo = (queue_lo + 1) % MAX_QUEUE;
283                          return;                          started = False;
284                  }                  }
285                    else
                 out->p += len;  
                 if (out->p == out->end)  
286                  {                  {
287                          long long duration;                          g_dsp_busy = 1;
288                          long elapsed;                          return;
   
                         gettimeofday(&tv, NULL);  
                         duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));  
                         elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);  
   
                         if (elapsed >= (duration * 85) / 100)  
                         {  
                                 rdpsnd_send_completion(packet->tick, packet->index);  
                                 free(out->data);  
                                 queue_lo = (queue_lo + 1) % MAX_QUEUE;  
                                 started = False;  
                         }  
                         else  
                         {  
                                 g_dsp_busy = 1;  
                                 return;  
                         }  
289                  }                  }
290          }          }
291            g_dsp_busy = 1;
292            return;
293  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26