/[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 476 by matthewc, Sat Oct 4 00:03:24 2003 UTC revision 1345 by ossman_, Thu Dec 7 11:54:29 2006 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/audio.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 BOOL g_reopened;
38  BOOL g_dsp_busy;  static short g_samplewidth;
39  static BOOL swapaudio;  static char *dsp_dev;
 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;  
40    
41  BOOL  BOOL
42  wave_out_open(void)  sun_open(void)
43  {  {
44          char *dsp_dev = "/dev/audio";          if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
   
         if ((g_dsp_fd = open(dsp_dev, O_WRONLY|O_NONBLOCK)) == -1)  
45          {          {
46                  perror(dsp_dev);                  perror(dsp_dev);
47                  return False;                  return False;
48          }          }
49    
   
50          /* Non-blocking so that user interface is responsive */          /* Non-blocking so that user interface is responsive */
51          fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL)|O_NONBLOCK);          fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
52          queue_lo = queue_hi = 0;  
53            g_reopened = True;
54    
55          return True;          return True;
56  }  }
57    
58  void  void
59  wave_out_close(void)  sun_close(void)
60  {  {
61          ioctl(g_dsp_fd,I_FLUSH,FLUSHW);          /* Ack all remaining packets */
62            while (!rdpsnd_queue_empty())
63                    rdpsnd_queue_next(0);
64    
65    #if defined I_FLUSH && defined FLUSHW
66            /* Flush the audiobuffer */
67            ioctl(g_dsp_fd, I_FLUSH, FLUSHW);
68    #endif
69    #if defined AUDIO_FLUSH
70            ioctl(g_dsp_fd, AUDIO_FLUSH, NULL);
71    #endif
72          close(g_dsp_fd);          close(g_dsp_fd);
73  }  }
74    
75  BOOL  BOOL
76  wave_out_format_supported(WAVEFORMATEX *pwfx)  sun_format_supported(WAVEFORMATEX * pwfx)
77  {  {
78          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
79                  return False;                  return False;
# Line 81  wave_out_format_supported(WAVEFORMATEX * Line 86  wave_out_format_supported(WAVEFORMATEX *
86  }  }
87    
88  BOOL  BOOL
89  wave_out_set_format(WAVEFORMATEX *pwfx)  sun_set_format(WAVEFORMATEX * pwfx)
90  {  {
91          audio_info_t info;          audio_info_t info;
         int test = 1;  
92    
93          ioctl(g_dsp_fd, AUDIO_DRAIN, 0);          ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
         swapaudio = False;  
94          AUDIO_INITINFO(&info);          AUDIO_INITINFO(&info);
95    
96    
97          if (pwfx->wBitsPerSample == 8)          if (pwfx->wBitsPerSample == 8)
98          {          {
99                  info.play.encoding = AUDIO_ENCODING_LINEAR8;                  info.play.encoding = AUDIO_ENCODING_LINEAR8;
                 samplewidth=1;  
100          }          }
101          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
102          {          {
103                  info.play.encoding = AUDIO_ENCODING_LINEAR;                  info.play.encoding = AUDIO_ENCODING_LINEAR;
                 swapaudio = !(*(uint8 *) (&test));  
                 samplewidth=2;  
104          }          }
105    
106          if (pwfx->nChannels == 1 )          g_samplewidth = pwfx->wBitsPerSample / 8;
107          {        
108                  info.play.channels = AUDIO_CHANNELS_MONO;          if (pwfx->nChannels == 1)
109            {
110                    info.play.channels = 1;
111          }          }
112          else if (pwfx->nChannels == 2 )          else if (pwfx->nChannels == 2)
113          {          {
114                  info.play.channels = AUDIO_CHANNELS_STEREO;                  info.play.channels = 2;
115                  samplewidth*=2;                  g_samplewidth *= 2;
116          }          }
117    
118          info.play.sample_rate = pwfx->nSamplesPerSec;          info.play.sample_rate = pwfx->nSamplesPerSec;
# Line 118  wave_out_set_format(WAVEFORMATEX *pwfx) Line 120  wave_out_set_format(WAVEFORMATEX *pwfx)
120          info.play.samples = 0;          info.play.samples = 0;
121          info.play.eof = 0;          info.play.eof = 0;
122          info.play.error = 0;          info.play.error = 0;
123            g_reopened = True;
124    
125          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
126          {          {
# Line 130  wave_out_set_format(WAVEFORMATEX *pwfx) Line 133  wave_out_set_format(WAVEFORMATEX *pwfx)
133  }  }
134    
135  void  void
136  wave_out_write(STREAM s, uint16 tick, uint8 index)  sun_volume(uint16 left, uint16 right)
137  {  {
138          struct audio_packet *packet = &packet_queue[queue_hi];          audio_info_t info;
139          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          uint balance;
140            uint volume;
141    
142            AUDIO_INITINFO(&info);
143    
144            volume = (left > right) ? left : right;
145    
146          if (next_hi == queue_lo)          if (volume / AUDIO_MID_BALANCE != 0)
147          {          {
148                  error("No space to queue audio packet\n");                  balance =
149                  return;                          AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
150                            (right / (volume / AUDIO_MID_BALANCE));
151            }
152            else
153            {
154                    balance = AUDIO_MID_BALANCE;
155          }          }
           
         queue_hi = next_hi;  
   
         packet->s = *s;  
         packet->tick = tick;  
         packet->index = index;  
156    
157          /* we steal the data buffer from s, give it a new one */          info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
158          s->data = malloc(s->size);          info.play.balance = balance;
159    
160          if (!g_dsp_busy)          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
161                  wave_out_play();          {
162                    perror("AUDIO_SETINFO");
163                    return;
164            }
165  }  }
166    
167  void  void
168  wave_out_play(void)  sun_play(void)
169  {  {
170          struct audio_packet *packet;          struct audio_packet *packet;
171          audio_info_t info;          audio_info_t info;
172          ssize_t len;          ssize_t len;
173          unsigned int i;          unsigned int i;
         uint8 swap;  
174          STREAM out;          STREAM out;
         static BOOL swapped = False;  
175          static BOOL sentcompletion = True;          static BOOL sentcompletion = True;
176          static int samplecnt;          static uint32 samplecnt = 0;
177          static int numsamples;          static uint32 numsamples;
178    
179          while (1)          while (1)
180          {          {
181                  if (queue_lo == queue_hi)                  if (g_reopened)
182                    {
183                            /* Device was just (re)openend */
184                            samplecnt = 0;
185                            sentcompletion = True;
186                            g_reopened = False;
187                    }
188    
189                    if (rdpsnd_queue_empty())
190                  {                  {
191                          g_dsp_busy = 0;                          g_dsp_busy = 0;
192                          return;                          return;
193                  }                  }
194    
195                  packet = &packet_queue[queue_lo];                  packet = rdpsnd_queue_current_packet();
196                  out = &packet->s;                  out = &packet->s;
197    
198                  if ( swapaudio && ! swapped )                  if (sentcompletion)
199                  {                  {
                         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 )  
                 {  
                         if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)  
                         {  
                                 perror("AUDIO_GETINFO");  
                                 return;  
                         }  
                         samplecnt=info.play.samples;  
200                          sentcompletion = False;                          sentcompletion = False;
201                          numsamples = (out->end-out->p)/samplewidth;                          numsamples = (out->end - out->p) / g_samplewidth;
202                  }                  }
203    
204                  len=0;                  len = 0;
205    
206                  if ( out->end - out->p != 0 )                  if (out->end != out->p)
207                  {                  {
208                          len = write(g_dsp_fd, out->p, out->end - out->p);                          len = write(g_dsp_fd, out->p, out->end - out->p);
209                          if (len == -1)                          if (len == -1)
# Line 224  wave_out_play(void) Line 223  wave_out_play(void)
223                                  perror("AUDIO_GETINFO");                                  perror("AUDIO_GETINFO");
224                                  return;                                  return;
225                          }                          }
226                          if ( info.play.samples >= samplecnt+(numsamples)*0.9 )  
227                            /* Ack the packet, if we have played at least 70% */
228                            if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
229                          {                          {
230                                  rdpsnd_send_completion(packet->tick, packet->index);                                  samplecnt += numsamples;
231                                  free(out->data);                                  /* We need to add 50 to tell windows that time has passed while
232                                  queue_lo = (queue_lo + 1) % MAX_QUEUE;                                   * playing this packet */
233                                  swapped = False;                                  rdpsnd_queue_next(50);
234                                  sentcompletion = True;                                  sentcompletion = True;
235                          }                          }
236                          else                          else
# Line 240  wave_out_play(void) Line 241  wave_out_play(void)
241                  }                  }
242          }          }
243  }  }
244    
245    static struct audio_driver sun_driver = {
246            .name = "sun",
247            .description = "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV",
248    
249            .wave_out_open = sun_open,
250            .wave_out_close = sun_close,
251            .wave_out_format_supported = sun_format_supported,
252            .wave_out_set_format = sun_set_format,
253            .wave_out_volume = sun_volume,
254            .wave_out_play = sun_play,
255    
256            .need_byteswap_on_be = 1,
257            .need_resampling = 0,
258    };
259    
260    struct audio_driver *
261    sun_register(char *options)
262    {
263            if (options)
264            {
265                    dsp_dev = xstrdup(options);
266            }
267            else
268            {
269                    dsp_dev = getenv("AUDIODEV");
270    
271                    if (dsp_dev == NULL)
272                    {
273                            dsp_dev = xstrdup(DEFAULTDEVICE);
274                    }
275            }
276    
277            return &sun_driver;
278    }

Legend:
Removed from v.476  
changed lines
  Added in v.1345

  ViewVC Help
Powered by ViewVC 1.1.26