/[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 477 by matthewc, Sat Oct 4 12:24:56 2003 UTC revision 1364 by jsorg71, Thu Jan 4 04:55:56 2007 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions - Sun     Sound Channel Process Functions - Sun
4     Copyright (C) Matthew Chapman 2003     Copyright (C) Matthew Chapman 2003
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     Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2006
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 21  Line 21 
21  */  */
22    
23  #include "rdesktop.h"  #include "rdesktop.h"
24    #include "rdpsnd.h"
25  #include <unistd.h>  #include <unistd.h>
26  #include <fcntl.h>  #include <fcntl.h>
27  #include <errno.h>  #include <errno.h>
28  #include <sys/ioctl.h>  #include <sys/ioctl.h>
29  #include <sys/audioio.h>  #include <sys/audioio.h>
30    
31    #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
32  #include <stropts.h>  #include <stropts.h>
33    #endif
34    
35  #define MAX_QUEUE       10  #define DEFAULTDEVICE   "/dev/audio"
36    
37  int g_dsp_fd;  static int dsp_fd = -1;
38  BOOL g_dsp_busy;  static BOOL dsp_busy;
 static BOOL reopened;  
 static BOOL swapaudio;  
 static short samplewidth;  
   
 static struct audio_packet {  
         struct stream s;  
         uint16 tick;  
         uint8 index;  
 } packet_queue[MAX_QUEUE];  
 static unsigned int queue_hi, queue_lo;  
39    
40  BOOL  static BOOL g_reopened;
41  wave_out_open(void)  static short g_samplewidth;
42    static char *dsp_dev;
43    
44    void sun_play(void);
45    
46    void
47    sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
48  {  {
49          char *dsp_dev = getenv("AUDIODEV");          if (dsp_fd == -1)
50                    return;
51    
52          if ( dsp_dev == NULL )          if (rdpsnd_queue_empty())
53          {                  return;
54                  dsp_dev="/dev/audio";  
55          }          FD_SET(dsp_fd, wfds);
56            if (dsp_fd > *n)
57                    *n = dsp_fd;
58    }
59    
60    void
61    sun_check_fds(fd_set * rfds, fd_set * wfds)
62    {
63            if (FD_ISSET(dsp_fd, wfds))
64                    sun_play();
65    }
66    
67          if ((g_dsp_fd = open(dsp_dev, O_WRONLY|O_NONBLOCK)) == -1)  BOOL
68    sun_open(void)
69    {
70            if ((dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
71          {          {
72                  perror(dsp_dev);                  perror(dsp_dev);
73                  return False;                  return False;
74          }          }
75    
76          /* Non-blocking so that user interface is responsive */          /* Non-blocking so that user interface is responsive */
77          fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL)|O_NONBLOCK);          fcntl(dsp_fd, F_SETFL, fcntl(dsp_fd, F_GETFL) | O_NONBLOCK);
78            
79          queue_lo = queue_hi = 0;          g_reopened = True;
80          reopened = True;  
           
81          return True;          return True;
82  }  }
83    
84  void  void
85  wave_out_close(void)  sun_close(void)
86  {  {
87          /* Ack all remaining packets */          /* Ack all remaining packets */
88          while ( queue_lo != queue_hi )          while (!rdpsnd_queue_empty())
89          {                  rdpsnd_queue_next(0);
                 rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);  
                 free(packet_queue[queue_lo].s.data);  
                 queue_lo = (queue_lo + 1) % MAX_QUEUE;  
         }  
90    
91    #if defined I_FLUSH && defined FLUSHW
92          /* Flush the audiobuffer */          /* Flush the audiobuffer */
93          ioctl(g_dsp_fd,I_FLUSH,FLUSHW);          ioctl(dsp_fd, I_FLUSH, FLUSHW);
94          close(g_dsp_fd);  #endif
95    #if defined AUDIO_FLUSH
96            ioctl(dsp_fd, AUDIO_FLUSH, NULL);
97    #endif
98            close(dsp_fd);
99            dsp_fd = -1;
100  }  }
101    
102  BOOL  BOOL
103  wave_out_format_supported(WAVEFORMATEX *pwfx)  sun_format_supported(RD_WAVEFORMATEX * pwfx)
104  {  {
105          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
106                  return False;                  return False;
# Line 98  wave_out_format_supported(WAVEFORMATEX * Line 113  wave_out_format_supported(WAVEFORMATEX *
113  }  }
114    
115  BOOL  BOOL
116  wave_out_set_format(WAVEFORMATEX *pwfx)  sun_set_format(RD_WAVEFORMATEX * pwfx)
117  {  {
118          audio_info_t info;          audio_info_t info;
         int test = 1;  
119    
120          ioctl(g_dsp_fd, AUDIO_DRAIN, 0);          ioctl(dsp_fd, AUDIO_DRAIN, 0);
         swapaudio = False;  
121          AUDIO_INITINFO(&info);          AUDIO_INITINFO(&info);
122    
123    
124          if (pwfx->wBitsPerSample == 8)          if (pwfx->wBitsPerSample == 8)
125          {          {
126                  info.play.encoding = AUDIO_ENCODING_LINEAR8;                  info.play.encoding = AUDIO_ENCODING_LINEAR8;
                 samplewidth = 1;  
127          }          }
128          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
129          {          {
130                  info.play.encoding = AUDIO_ENCODING_LINEAR;                  info.play.encoding = AUDIO_ENCODING_LINEAR;
                 samplewidth = 2;  
                 /* Do we need to swap the 16bit values? (Are we BigEndian) */  
                 swapaudio = !(*(uint8 *) (&test));  
131          }          }
132    
133          if (pwfx->nChannels == 1 )          g_samplewidth = pwfx->wBitsPerSample / 8;
134          {        
135                  info.play.channels = AUDIO_CHANNELS_MONO;          if (pwfx->nChannels == 1)
136            {
137                    info.play.channels = 1;
138          }          }
139          else if (pwfx->nChannels == 2 )          else if (pwfx->nChannels == 2)
140          {          {
141                  info.play.channels = AUDIO_CHANNELS_STEREO;                  info.play.channels = 2;
142                  samplewidth *= 2;                  g_samplewidth *= 2;
143          }          }
144    
145          info.play.sample_rate = pwfx->nSamplesPerSec;          info.play.sample_rate = pwfx->nSamplesPerSec;
# Line 136  wave_out_set_format(WAVEFORMATEX *pwfx) Line 147  wave_out_set_format(WAVEFORMATEX *pwfx)
147          info.play.samples = 0;          info.play.samples = 0;
148          info.play.eof = 0;          info.play.eof = 0;
149          info.play.error = 0;          info.play.error = 0;
150            g_reopened = True;
151    
152          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)          if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
153          {          {
154                  perror("AUDIO_SETINFO");                  perror("AUDIO_SETINFO");
155                  close(g_dsp_fd);                  sun_close();
156                  return False;                  return False;
157          }          }
158    
# Line 148  wave_out_set_format(WAVEFORMATEX *pwfx) Line 160  wave_out_set_format(WAVEFORMATEX *pwfx)
160  }  }
161    
162  void  void
163  wave_out_write(STREAM s, uint16 tick, uint8 index)  sun_volume(uint16 left, uint16 right)
164  {  {
165          struct audio_packet *packet = &packet_queue[queue_hi];          audio_info_t info;
166          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          uint balance;
167            uint volume;
168    
169            AUDIO_INITINFO(&info);
170    
171            volume = (left > right) ? left : right;
172    
173          if (next_hi == queue_lo)          if (volume / AUDIO_MID_BALANCE != 0)
174          {          {
175                  error("No space to queue audio packet\n");                  balance =
176                  return;                          AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
177                            (right / (volume / AUDIO_MID_BALANCE));
178            }
179            else
180            {
181                    balance = AUDIO_MID_BALANCE;
182          }          }
           
         queue_hi = next_hi;  
   
         packet->s = *s;  
         packet->tick = tick;  
         packet->index = index;  
183    
184          /* we steal the data buffer from s, give it a new one */          info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
185          s->data = malloc(s->size);          info.play.balance = balance;
186    
187          if (!g_dsp_busy)          if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
188                  wave_out_play();          {
189                    perror("AUDIO_SETINFO");
190                    return;
191            }
192  }  }
193    
194  void  void
195  wave_out_play(void)  sun_play(void)
196  {  {
197          struct audio_packet *packet;          struct audio_packet *packet;
198          audio_info_t info;          audio_info_t info;
199          ssize_t len;          ssize_t len;
200          unsigned int i;          unsigned int i;
         uint8 swap;  
201          STREAM out;          STREAM out;
         static BOOL swapped = False;  
202          static BOOL sentcompletion = True;          static BOOL sentcompletion = True;
203          static uint32 samplecnt = 0;          static uint32 samplecnt = 0;
204          static uint32 numsamples;          static uint32 numsamples;
205    
206          while (1)          while (1)
207          {          {
208                  if ( reopened )                  if (g_reopened)
209                  {                  {
210                          /* Device was just (re)openend */                          /* Device was just (re)openend */
211                          samplecnt = 0;                          samplecnt = 0;
                         swapped = False;  
212                          sentcompletion = True;                          sentcompletion = True;
213                          reopened = False;                          g_reopened = False;
214                  }                  }
215    
216                  if (queue_lo == queue_hi)                  if (rdpsnd_queue_empty())
                 {  
                         g_dsp_busy = 0;  
217                          return;                          return;
                 }  
218    
219                  packet = &packet_queue[queue_lo];                  packet = rdpsnd_queue_current_packet();
220                  out = &packet->s;                  out = &packet->s;
221    
222                  /* Swap the current packet, but only once */                  if (sentcompletion)
                 if ( swapaudio && ! swapped )  
                 {  
                         for ( i = 0; i < out->end - out->p; i+=2 )  
                         {  
                                 swap = *(out->p + i);  
                                 *(out->p + i ) = *(out->p + i + 1);  
                                 *(out->p + i + 1) = swap;  
                                 swapped = True;  
                         }  
                 }  
   
                 if ( sentcompletion )  
223                  {                  {
224                          sentcompletion = False;                          sentcompletion = False;
225                          numsamples = (out->end - out->p)/samplewidth;                          numsamples = (out->end - out->p) / g_samplewidth;
226                  }                  }
227    
228                  len=0;                  len = 0;
229    
230                  if ( out->end != out->p )                  if (out->end != out->p)
231                  {                  {
232                          len = write(g_dsp_fd, out->p, out->end - out->p);                          len = write(dsp_fd, out->p, out->end - out->p);
233                          if (len == -1)                          if (len == -1)
234                          {                          {
235                                  if (errno != EWOULDBLOCK)                                  if (errno != EWOULDBLOCK)
236                                          perror("write audio");                                          perror("write audio");
                                 g_dsp_busy = 1;  
237                                  return;                                  return;
238                          }                          }
239                  }                  }
# Line 241  wave_out_play(void) Line 241  wave_out_play(void)
241                  out->p += len;                  out->p += len;
242                  if (out->p == out->end)                  if (out->p == out->end)
243                  {                  {
244                          if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)                          if (ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
245                          {                          {
246                                  perror("AUDIO_GETINFO");                                  perror("AUDIO_GETINFO");
247                                  return;                                  return;
248                          }                          }
249    
250                          /* Ack the packet, if we have played at least 70% */                          /* Ack the packet, if we have played at least 70% */
251                          if ( info.play.samples >= samplecnt+((numsamples*7)/10) )                          if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
252                          {                          {
253                                  samplecnt += numsamples;                                  samplecnt += numsamples;
254                                  rdpsnd_send_completion(packet->tick, packet->index);                                  /* We need to add 50 to tell windows that time has passed while
255                                  free(out->data);                                   * playing this packet */
256                                  queue_lo = (queue_lo + 1) % MAX_QUEUE;                                  rdpsnd_queue_next(50);
                                 swapped = False;  
257                                  sentcompletion = True;                                  sentcompletion = True;
258                          }                          }
259                          else                          else
260                          {                          {
                                 g_dsp_busy = 1;  
261                                  return;                                  return;
262                          }                          }
263                  }                  }
264          }          }
265  }  }
266    
267    struct audio_driver *
268    sun_register(char *options)
269    {
270            static struct audio_driver sun_driver;
271    
272            memset(&sun_driver, 0, sizeof(sun_driver));
273    
274            sun_driver.name = "sun";
275            sun_driver.description =
276                    "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV";
277    
278            sun_driver.add_fds = sun_add_fds;
279            sun_driver.check_fds = sun_check_fds;
280    
281            sun_driver.wave_out_open = sun_open;
282            sun_driver.wave_out_close = sun_close;
283            sun_driver.wave_out_format_supported = sun_format_supported;
284            sun_driver.wave_out_set_format = sun_set_format;
285            sun_driver.wave_out_volume = sun_volume;
286    
287            sun_driver.need_byteswap_on_be = 1;
288            sun_driver.need_resampling = 0;
289    
290            if (options)
291            {
292                    dsp_dev = xstrdup(options);
293            }
294            else
295            {
296                    dsp_dev = getenv("AUDIODEV");
297    
298                    if (dsp_dev == NULL)
299                    {
300                            dsp_dev = DEFAULTDEVICE;
301                    }
302            }
303    
304            return &sun_driver;
305    }

Legend:
Removed from v.477  
changed lines
  Added in v.1364

  ViewVC Help
Powered by ViewVC 1.1.26