/[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 1365 by jsorg71, Thu Jan 4 05:39:39 2007 UTC revision 1481 by astrand, Thu Oct 2 18:21:58 2008 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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-2007     Copyright (C) Matthew Chapman 2003-2008
5     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6     Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB     Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
7    
8     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 28  Line 28 
28  #undef _FILE_OFFSET_BITS  #undef _FILE_OFFSET_BITS
29  #endif  #endif
30    
31    #include <assert.h>
32    
33  #include "rdesktop.h"  #include "rdesktop.h"
34  #include "rdpsnd.h"  #include "rdpsnd.h"
35  #include "rdpsnd_dsp.h"  #include "rdpsnd_dsp.h"
# Line 46  Line 48 
48    
49  static int dsp_fd = -1;  static int dsp_fd = -1;
50  static int dsp_mode;  static int dsp_mode;
 static int dsp_refs;  
   
 static BOOL dsp_configured;  
51    
52  static BOOL dsp_out;  static RD_BOOL dsp_configured;
53  static BOOL dsp_in;  static RD_BOOL dsp_broken;
54    
55  static int stereo;  static int stereo;
56  static int format;  static int format;
57  static int snd_rate;  static uint32 snd_rate;
58  static short samplewidth;  static short samplewidth;
59  static char *dsp_dev;  static char *dsp_dev;
60  static BOOL in_esddsp;  static RD_BOOL in_esddsp;
61    
62  /* This is a just a forward declaration */  /* This is a just a forward declaration */
63  static struct audio_driver oss_driver;  static struct audio_driver oss_driver;
64    
65  void oss_play(void);  static void oss_play(void);
66  void oss_record(void);  static void oss_record(void);
67    static RD_BOOL oss_set_format(RD_WAVEFORMATEX * pwfx);
68    
69  void  static void
70  oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)  oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
71  {  {
72          if (dsp_fd == -1)          if (dsp_fd == -1)
73                  return;                  return;
74    
75          if (dsp_out && !rdpsnd_queue_empty())          if ((dsp_mode == O_WRONLY || dsp_mode == O_RDWR) && !rdpsnd_queue_empty())
76                  FD_SET(dsp_fd, wfds);                  FD_SET(dsp_fd, wfds);
77          if (dsp_in)          if (dsp_mode == O_RDONLY || dsp_mode == O_RDWR)
78                  FD_SET(dsp_fd, rfds);                  FD_SET(dsp_fd, rfds);
79          if (dsp_fd > *n)          if (dsp_fd > *n)
80                  *n = dsp_fd;                  *n = dsp_fd;
81  }  }
82    
83  void  static void
84  oss_check_fds(fd_set * rfds, fd_set * wfds)  oss_check_fds(fd_set * rfds, fd_set * wfds)
85  {  {
86          if (FD_ISSET(dsp_fd, wfds))          if (FD_ISSET(dsp_fd, wfds))
# Line 89  oss_check_fds(fd_set * rfds, fd_set * wf Line 89  oss_check_fds(fd_set * rfds, fd_set * wf
89                  oss_record();                  oss_record();
90  }  }
91    
92  static BOOL  static RD_BOOL
93  detect_esddsp(void)  detect_esddsp(void)
94  {  {
95          struct stat s;          struct stat s;
# Line 111  detect_esddsp(void) Line 111  detect_esddsp(void)
111          return True;          return True;
112  }  }
113    
 BOOL  
 oss_open(int fallback)  
 {  
         int caps;  
   
         if (dsp_fd != -1)  
         {  
                 dsp_refs++;  
   
                 if (dsp_mode == O_RDWR)  
                         return True;  
   
                 if (dsp_mode == fallback)  
                         return True;  
114    
115                  dsp_refs--;  static void
116                  return False;  oss_restore_format()
117          }  {
118            RD_WAVEFORMATEX wfx;
119            memset(&wfx, 0, sizeof(RD_WAVEFORMATEX));
120            switch (format)
121            {
122                    case AFMT_U8:
123                            wfx.wBitsPerSample = 8;
124                            break;
125                    case AFMT_S16_LE:
126                            wfx.wBitsPerSample = 16;
127                            break;
128                    default:
129                            wfx.wBitsPerSample = 0;
130            }
131            wfx.nChannels = stereo ? 2 : 1;
132            wfx.nSamplesPerSec = snd_rate;
133            oss_set_format(&wfx);
134    }
135    
         dsp_configured = False;  
136    
137          dsp_mode = O_RDWR;  static RD_BOOL
138          dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK);  oss_open(int wanted)
139    {
140          if (dsp_fd != -1)          if (dsp_fd != -1)
141          {          {
142                  ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0);                  if (wanted == dsp_mode)
143                    {
144                  if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0) || !(caps & DSP_CAP_DUPLEX))                          /* should probably not happen */
145                            return True;
146                    }
147                    else
148                  {                  {
149                            /* device open but not our mode. Before
150                               reopening O_RDWR, verify that the device is
151                               duplex capable */
152                            int caps;
153                            ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0);
154                            if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0)
155                                || !(caps & DSP_CAP_DUPLEX))
156                            {
157                                    warning("This device is not capable of full duplex operation.\n");
158                                    return False;
159                            }
160                          close(dsp_fd);                          close(dsp_fd);
161                          dsp_fd = -1;                          dsp_mode = O_RDWR;
162                  }                  }
163          }          }
164            else
165            {
166                    dsp_mode = wanted;
167            }
168    
169            dsp_configured = False;
170            dsp_broken = False;
171    
172            dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
173    
174          if (dsp_fd == -1)          if (dsp_fd == -1)
175          {          {
176                  dsp_mode = fallback;                  perror(dsp_dev);
177                    return False;
                 dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);  
                 if (dsp_fd == -1)  
                 {  
                         perror(dsp_dev);  
                         return False;  
                 }  
178          }          }
179    
         dsp_refs++;  
   
180          in_esddsp = detect_esddsp();          in_esddsp = detect_esddsp();
181    
182          return True;          return True;
183  }  }
184    
185  void  static void
186  oss_close(void)  oss_close(void)
187  {  {
         dsp_refs--;  
   
         if (dsp_refs != 0)  
                 return;  
   
188          close(dsp_fd);          close(dsp_fd);
189          dsp_fd = -1;          dsp_fd = -1;
190  }  }
191    
192  BOOL  static RD_BOOL
193  oss_open_out(void)  oss_open_out(void)
194  {  {
195          if (!oss_open(O_WRONLY))          if (!oss_open(O_WRONLY))
196                  return False;                  return False;
197    
         dsp_out = True;  
   
198          return True;          return True;
199  }  }
200    
201  void  static void
202  oss_close_out(void)  oss_close_out(void)
203  {  {
204          oss_close();          oss_close();
205            if (dsp_mode == O_RDWR)
206            {
207                    if (oss_open(O_RDONLY))
208                            oss_restore_format();
209            }
210    
211          /* Ack all remaining packets */          /* Ack all remaining packets */
212          while (!rdpsnd_queue_empty())          while (!rdpsnd_queue_empty())
213                  rdpsnd_queue_next(0);                  rdpsnd_queue_next(0);
   
         dsp_out = False;  
214  }  }
215    
216  BOOL  static RD_BOOL
217  oss_open_in(void)  oss_open_in(void)
218  {  {
219          if (!oss_open(O_RDONLY))          if (!oss_open(O_RDONLY))
220                  return False;                  return False;
221    
         dsp_in = True;  
   
222          return True;          return True;
223  }  }
224    
225  void  static void
226  oss_close_in(void)  oss_close_in(void)
227  {  {
228          oss_close();          oss_close();
229            if (dsp_mode == O_RDWR)
230          dsp_in = False;          {
231                    if (oss_open(O_WRONLY))
232                            oss_restore_format();
233            }
234  }  }
235    
236  BOOL  static RD_BOOL
237  oss_format_supported(RD_WAVEFORMATEX * pwfx)  oss_format_supported(RD_WAVEFORMATEX * pwfx)
238  {  {
239          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
# Line 231  oss_format_supported(RD_WAVEFORMATEX * p Line 246  oss_format_supported(RD_WAVEFORMATEX * p
246          return True;          return True;
247  }  }
248    
249  BOOL  static RD_BOOL
250  oss_set_format(RD_WAVEFORMATEX * pwfx)  oss_set_format(RD_WAVEFORMATEX * pwfx)
251  {  {
252          int fragments;          int fragments;
253          static BOOL driver_broken = False;          static RD_BOOL driver_broken = False;
254    
255            assert(dsp_fd != -1);
256    
257          if (dsp_configured)          if (dsp_configured)
258          {          {
# Line 291  oss_set_format(RD_WAVEFORMATEX * pwfx) Line 308  oss_set_format(RD_WAVEFORMATEX * pwfx)
308          snd_rate = pwfx->nSamplesPerSec;          snd_rate = pwfx->nSamplesPerSec;
309          if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)          if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
310          {          {
311                  int rates[] = { 44100, 48000, 0 };                  uint32 rates[] = { 44100, 48000, 0 };
312                  int *prates = rates;                  uint32 *prates = rates;
313    
314                  while (*prates != 0)                  while (*prates != 0)
315                  {                  {
# Line 352  oss_set_format(RD_WAVEFORMATEX * pwfx) Line 369  oss_set_format(RD_WAVEFORMATEX * pwfx)
369          return True;          return True;
370  }  }
371    
372  void  static void
373  oss_volume(uint16 left, uint16 right)  oss_volume(uint16 left, uint16 right)
374  {  {
375          uint32 volume;          uint32 volume;
# Line 369  oss_volume(uint16 left, uint16 right) Line 386  oss_volume(uint16 left, uint16 right)
386          }          }
387  }  }
388    
389  void  static void
390  oss_play(void)  oss_play(void)
391  {  {
392          struct audio_packet *packet;          struct audio_packet *packet;
393          ssize_t len;          ssize_t len;
394          STREAM out;          STREAM out;
395    
396            assert(dsp_fd != -1);
397    
398          /* We shouldn't be called if the queue is empty, but still */          /* We shouldn't be called if the queue is empty, but still */
399          if (rdpsnd_queue_empty())          if (rdpsnd_queue_empty())
400                  return;                  return;
# Line 389  oss_play(void) Line 408  oss_play(void)
408          if (len == -1)          if (len == -1)
409          {          {
410                  if (errno != EWOULDBLOCK)                  if (errno != EWOULDBLOCK)
411                          perror("write audio");                  {
412                            if (!dsp_broken)
413                                    perror("RDPSND: write()");
414                            dsp_broken = True;
415                            rdpsnd_queue_next(0);
416                    }
417                  return;                  return;
418          }          }
419    
420            dsp_broken = False;
421    
422          out->p += len;          out->p += len;
423    
424          if (out->p == out->end)          if (out->p == out->end)
# Line 431  oss_play(void) Line 457  oss_play(void)
457          }          }
458  }  }
459    
460  void  static void
461  oss_record(void)  oss_record(void)
462  {  {
463          char buffer[32768];          char buffer[32768];
464          int len;          int len;
465    
466            assert(dsp_fd != -1);
467    
468          len = read(dsp_fd, buffer, sizeof(buffer));          len = read(dsp_fd, buffer, sizeof(buffer));
469          if (len == -1)          if (len == -1)
470          {          {
471                  if (errno != EWOULDBLOCK)                  if (errno != EWOULDBLOCK)
472                          perror("read audio");                  {
473                            if (!dsp_broken)
474                                    perror("RDPSND: read()");
475                            dsp_broken = True;
476                            rdpsnd_queue_next(0);
477                    }
478                  return;                  return;
479          }          }
480    
481            dsp_broken = False;
482    
483          rdpsnd_record(buffer, len);          rdpsnd_record(buffer, len);
484  }  }
485    

Legend:
Removed from v.1365  
changed lines
  Added in v.1481

  ViewVC Help
Powered by ViewVC 1.1.26