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

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

revision 1427 by jsorg71, Mon Jan 8 04:47:06 2007 UTC revision 1428 by ossman_, Tue Jan 22 10:42:55 2008 UTC
# Line 4  Line 4 
4     Copyright (C) Matthew Chapman 2003-2007     Copyright (C) Matthew Chapman 2003-2007
5     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6     Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2007     Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2007
7       Copyright 2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8    
9     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
10     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 33  Line 34 
34  #endif  #endif
35    
36  #define DEFAULTDEVICE   "/dev/audio"  #define DEFAULTDEVICE   "/dev/audio"
37    #define MAX_LEN         512
38    
39  static int dsp_fd = -1;  static int dsp_fd = -1;
40  static RD_BOOL dsp_busy;  static int dsp_mode;
41    static int dsp_refs;
42    
43  static RD_BOOL g_reopened;  static RD_BOOL dsp_configured;
44  static short g_samplewidth;  static RD_BOOL dsp_broken;
45    
46    static RD_BOOL dsp_out;
47    static RD_BOOL dsp_in;
48    
49    static int stereo;
50    static int format;
51    static uint32 snd_rate;
52    static short samplewidth;
53  static char *dsp_dev;  static char *dsp_dev;
54    
55    static uint_t written_samples;
56    
57  void sun_play(void);  void sun_play(void);
58    void sun_record(void);
59    
60  void  void
61  sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)  sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
# Line 49  sun_add_fds(int *n, fd_set * rfds, fd_se Line 63  sun_add_fds(int *n, fd_set * rfds, fd_se
63          if (dsp_fd == -1)          if (dsp_fd == -1)
64                  return;                  return;
65    
66          if (rdpsnd_queue_empty())          if (dsp_out && !rdpsnd_queue_empty())
67                  return;                  FD_SET(dsp_fd, wfds);
68            if (dsp_in)
69          FD_SET(dsp_fd, wfds);                  FD_SET(dsp_fd, rfds);
70          if (dsp_fd > *n)          if (dsp_fd > *n)
71                  *n = dsp_fd;                  *n = dsp_fd;
72  }  }
# Line 62  sun_check_fds(fd_set * rfds, fd_set * wf Line 76  sun_check_fds(fd_set * rfds, fd_set * wf
76  {  {
77          if (FD_ISSET(dsp_fd, wfds))          if (FD_ISSET(dsp_fd, wfds))
78                  sun_play();                  sun_play();
79            if (FD_ISSET(dsp_fd, rfds))
80                    sun_record();
81  }  }
82    
83  RD_BOOL  RD_BOOL
84  sun_open(void)  sun_open(int mode)
85  {  {
86          if ((dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)          audio_info_t info;
87    
88            if (dsp_fd != -1)
89          {          {
90                  perror(dsp_dev);                  dsp_refs++;
91    
92                    if (dsp_mode == O_RDWR)
93                            return True;
94    
95                    if (dsp_mode == mode)
96                            return True;
97    
98                    dsp_refs--;
99                  return False;                  return False;
100          }          }
101    
102          /* Non-blocking so that user interface is responsive */          dsp_configured = False;
103          fcntl(dsp_fd, F_SETFL, fcntl(dsp_fd, F_GETFL) | O_NONBLOCK);          dsp_broken = False;
104    
105            written_samples = 0;
106    
107            dsp_mode = O_RDWR;
108            dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK);
109            if (dsp_fd != -1)
110            {
111                    AUDIO_INITINFO(&info);
112    
113                    if ((ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
114                        || !(info.hw_features & AUDIO_HWFEATURE_DUPLEX))
115                    {
116                            close(dsp_fd);
117                            dsp_fd = -1;
118                    }
119            }
120    
121            if (dsp_fd == -1)
122            {
123                    dsp_mode = mode;
124    
125                    dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
126                    if (dsp_fd == -1)
127                    {
128                            perror(dsp_dev);
129                            return False;
130                    }
131            }
132    
133          g_reopened = True;          dsp_refs++;
134    
135          return True;          return True;
136  }  }
# Line 84  sun_open(void) Line 138  sun_open(void)
138  void  void
139  sun_close(void)  sun_close(void)
140  {  {
141          /* Ack all remaining packets */          dsp_refs--;
142          while (!rdpsnd_queue_empty())  
143                  rdpsnd_queue_next(0);          if (dsp_refs != 0)
144                    return;
145    
146            close(dsp_fd);
147            dsp_fd = -1;
148    }
149    
150    RD_BOOL
151    sun_open_out(void)
152    {
153            if (!sun_open(O_WRONLY))
154                    return False;
155    
156            dsp_out = True;
157    
158            return True;
159    }
160    
161    void
162    sun_close_out(void)
163    {
164  #if defined I_FLUSH && defined FLUSHW  #if defined I_FLUSH && defined FLUSHW
165          /* Flush the audiobuffer */          /* Flush the audiobuffer */
166          ioctl(dsp_fd, I_FLUSH, FLUSHW);          ioctl(dsp_fd, I_FLUSH, FLUSHW);
# Line 95  sun_close(void) Line 168  sun_close(void)
168  #if defined AUDIO_FLUSH  #if defined AUDIO_FLUSH
169          ioctl(dsp_fd, AUDIO_FLUSH, NULL);          ioctl(dsp_fd, AUDIO_FLUSH, NULL);
170  #endif  #endif
171          close(dsp_fd);  
172          dsp_fd = -1;          sun_close();
173    
174            /* Ack all remaining packets */
175            while (!rdpsnd_queue_empty())
176                    rdpsnd_queue_next(0);
177    
178            dsp_out = False;
179    }
180    
181    RD_BOOL
182    sun_open_in(void)
183    {
184            if (!sun_open(O_RDONLY))
185                    return False;
186    
187            dsp_in = True;
188    
189            return True;
190    }
191    
192    void
193    sun_close_in(void)
194    {
195            sun_close();
196    
197            dsp_in = False;
198  }  }
199    
200  RD_BOOL  RD_BOOL
# Line 120  sun_set_format(RD_WAVEFORMATEX * pwfx) Line 218  sun_set_format(RD_WAVEFORMATEX * pwfx)
218          ioctl(dsp_fd, AUDIO_DRAIN, 0);          ioctl(dsp_fd, AUDIO_DRAIN, 0);
219          AUDIO_INITINFO(&info);          AUDIO_INITINFO(&info);
220    
221            if (dsp_configured)
222            {
223                    if ((pwfx->wBitsPerSample == 8) && (format != AUDIO_ENCODING_LINEAR8))
224                            return False;
225                    if ((pwfx->wBitsPerSample == 16) && (format != AUDIO_ENCODING_LINEAR))
226                            return False;
227    
228                    if ((pwfx->nChannels == 2) != !!stereo)
229                            return False;
230    
231                    if (pwfx->nSamplesPerSec != snd_rate)
232                            return False;
233    
234                    return True;
235            }
236    
237          if (pwfx->wBitsPerSample == 8)          if (pwfx->wBitsPerSample == 8)
238          {          {
# Line 130  sun_set_format(RD_WAVEFORMATEX * pwfx) Line 243  sun_set_format(RD_WAVEFORMATEX * pwfx)
243                  info.play.encoding = AUDIO_ENCODING_LINEAR;                  info.play.encoding = AUDIO_ENCODING_LINEAR;
244          }          }
245    
246          g_samplewidth = pwfx->wBitsPerSample / 8;          samplewidth = pwfx->wBitsPerSample / 8;
247    
248          if (pwfx->nChannels == 1)          if (pwfx->nChannels == 1)
249          {          {
# Line 139  sun_set_format(RD_WAVEFORMATEX * pwfx) Line 252  sun_set_format(RD_WAVEFORMATEX * pwfx)
252          else if (pwfx->nChannels == 2)          else if (pwfx->nChannels == 2)
253          {          {
254                  info.play.channels = 2;                  info.play.channels = 2;
255                  g_samplewidth *= 2;                  samplewidth *= 2;
256          }          }
257    
258            snd_rate = pwfx->nSamplesPerSec;
259    
260          info.play.sample_rate = pwfx->nSamplesPerSec;          info.play.sample_rate = pwfx->nSamplesPerSec;
261          info.play.precision = pwfx->wBitsPerSample;          info.play.precision = pwfx->wBitsPerSample;
262          info.play.samples = 0;          info.play.samples = 0;
263          info.play.eof = 0;          info.play.eof = 0;
264          info.play.error = 0;          info.play.error = 0;
265          g_reopened = True;  
266            info.record.sample_rate = info.play.sample_rate;
267            info.record.channels = info.play.channels;
268            info.record.precision = info.play.precision;
269            info.record.encoding = info.play.encoding;
270            info.record.samples = 0;
271            info.record.error = 0;
272    
273          if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)          if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
274          {          {
# Line 156  sun_set_format(RD_WAVEFORMATEX * pwfx) Line 277  sun_set_format(RD_WAVEFORMATEX * pwfx)
277                  return False;                  return False;
278          }          }
279    
280            dsp_configured = True;
281    
282          return True;          return True;
283  }  }
284    
# Line 195  void Line 318  void
318  sun_play(void)  sun_play(void)
319  {  {
320          struct audio_packet *packet;          struct audio_packet *packet;
         audio_info_t info;  
321          ssize_t len;          ssize_t len;
         unsigned int i;  
322          STREAM out;          STREAM out;
         static RD_BOOL sentcompletion = True;  
         static uint32 samplecnt = 0;  
         static uint32 numsamples;  
323    
324          while (1)          /* We shouldn't be called if the queue is empty, but still */
325            if (rdpsnd_queue_empty())
326                    return;
327    
328            packet = rdpsnd_queue_current_packet();
329            out = &packet->s;
330    
331            len = out->end - out->p;
332    
333            len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
334            if (len == -1)
335          {          {
336                  if (g_reopened)                  if (errno != EWOULDBLOCK)
337                  {                  {
338                          /* Device was just (re)openend */                          if (!dsp_broken)
339                          samplecnt = 0;                                  perror("RDPSND: write()");
340                          sentcompletion = True;                          dsp_broken = True;
341                          g_reopened = False;                          rdpsnd_queue_next(0);
342                  }                  }
343                    return;
344            }
345    
346                  if (rdpsnd_queue_empty())          written_samples += len / (samplewidth * (stereo ? 2 : 1));
                         return;  
347    
348                  packet = rdpsnd_queue_current_packet();          dsp_broken = False;
                 out = &packet->s;  
349    
350                  if (sentcompletion)          out->p += len;
                 {  
                         sentcompletion = False;  
                         numsamples = (out->end - out->p) / g_samplewidth;  
                 }  
351    
352                  len = 0;          if (out->p == out->end)
353            {
354                    audio_info_t info;
355                    uint_t delay_samples;
356                    unsigned long delay_us;
357    
358                    if (ioctl(dsp_fd, AUDIO_GETINFO, &info) != -1)
359                            delay_samples = written_samples - info.play.samples;
360                    else
361                            delay_samples = out->size / (samplewidth * (stereo ? 2 : 1));
362    
363                  if (out->end != out->p)                  delay_us = delay_samples * (1000000 / snd_rate);
364                  {                  rdpsnd_queue_next(delay_us);
365                          len = write(dsp_fd, out->p, out->end - out->p);          }
366                          if (len == -1)  }
                         {  
                                 if (errno != EWOULDBLOCK)  
                                         perror("write audio");  
                                 return;  
                         }  
                 }  
367    
368                  out->p += len;  void
369                  if (out->p == out->end)  sun_record(void)
370                  {  {
371                          if (ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)          char buffer[32768];
372                          {          int len;
373                                  perror("AUDIO_GETINFO");  
374                                  return;          len = read(dsp_fd, buffer, sizeof(buffer));
375                          }          if (len == -1)
376            {
377                          /* Ack the packet, if we have played at least 70% */                  if (errno != EWOULDBLOCK)
378                          if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))                          perror("read audio");
379                          {                  return;
                                 samplecnt += numsamples;  
                                 /* We need to add 50 to tell windows that time has passed while  
                                  * playing this packet */  
                                 rdpsnd_queue_next(50);  
                                 sentcompletion = True;  
                         }  
                         else  
                         {  
                                 return;  
                         }  
                 }  
380          }          }
381    
382            rdpsnd_record(buffer, len);
383  }  }
384    
385  struct audio_driver *  struct audio_driver *
# Line 278  sun_register(char *options) Line 396  sun_register(char *options)
396          sun_driver.add_fds = sun_add_fds;          sun_driver.add_fds = sun_add_fds;
397          sun_driver.check_fds = sun_check_fds;          sun_driver.check_fds = sun_check_fds;
398    
399          sun_driver.wave_out_open = sun_open;          sun_driver.wave_out_open = sun_open_out;
400          sun_driver.wave_out_close = sun_close;          sun_driver.wave_out_close = sun_close_out;
401          sun_driver.wave_out_format_supported = sun_format_supported;          sun_driver.wave_out_format_supported = sun_format_supported;
402          sun_driver.wave_out_set_format = sun_set_format;          sun_driver.wave_out_set_format = sun_set_format;
403          sun_driver.wave_out_volume = sun_volume;          sun_driver.wave_out_volume = sun_volume;
404    
405            sun_driver.wave_in_open = sun_open_in;
406            sun_driver.wave_in_close = sun_close_in;
407            sun_driver.wave_in_format_supported = sun_format_supported;
408            sun_driver.wave_in_set_format = sun_set_format;
409            sun_driver.wave_in_volume = NULL;       /* FIXME */
410    
411          sun_driver.need_byteswap_on_be = 1;          sun_driver.need_byteswap_on_be = 1;
412          sun_driver.need_resampling = 0;          sun_driver.need_resampling = 0;
413    

Legend:
Removed from v.1427  
changed lines
  Added in v.1428

  ViewVC Help
Powered by ViewVC 1.1.26