/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/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 1254 by stargo, Sun Sep 17 10:32:18 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/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 BOOL g_reopened;
38  BOOL g_dsp_busy;  static BOOL g_swapaudio;
39  static BOOL reopened;  static short g_samplewidth;
 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;  
40    
41  BOOL  BOOL
42  wave_out_open(void)  wave_out_open(void)
43  {  {
44          char *dsp_dev = getenv("AUDIODEV");          char *dsp_dev = getenv("AUDIODEV");
45    
46          if ( dsp_dev == NULL )          if (dsp_dev == NULL)
47          {          {
48                  dsp_dev="/dev/audio";                  dsp_dev = xstrdup(DEFAULTDEVICE);
49          }          }
50    
51          if ((g_dsp_fd = open(dsp_dev, O_WRONLY|O_NONBLOCK)) == -1)          if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
52          {          {
53                  perror(dsp_dev);                  perror(dsp_dev);
54                  return False;                  return False;
55          }          }
56    
57          /* Non-blocking so that user interface is responsive */          /* Non-blocking so that user interface is responsive */
58          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);
59            
60          queue_lo = queue_hi = 0;          rdpsnd_queue_init();
61          reopened = True;          g_reopened = True;
62            
63          return True;          return True;
64  }  }
65    
# Line 72  void Line 67  void
67  wave_out_close(void)  wave_out_close(void)
68  {  {
69          /* Ack all remaining packets */          /* Ack all remaining packets */
70          while ( queue_lo != queue_hi )          while (!rdpsnd_queue_empty())
71          {          {
72                  rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);                  rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
73                  free(packet_queue[queue_lo].s.data);                                         rdpsnd_queue_current_packet()->index);
74                  queue_lo = (queue_lo + 1) % MAX_QUEUE;                  rdpsnd_queue_next();
75          }          }
76    
77    #if defined I_FLUSH && defined FLUSHW
78          /* Flush the audiobuffer */          /* Flush the audiobuffer */
79          ioctl(g_dsp_fd,I_FLUSH,FLUSHW);          ioctl(g_dsp_fd, I_FLUSH, FLUSHW);
80    #endif
81    #if defined AUDIO_FLUSH
82            ioctl(g_dsp_fd, AUDIO_FLUSH, NULL);
83    #endif
84          close(g_dsp_fd);          close(g_dsp_fd);
85  }  }
86    
87  BOOL  BOOL
88  wave_out_format_supported(WAVEFORMATEX *pwfx)  wave_out_format_supported(WAVEFORMATEX * pwfx)
89  {  {
90          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)          if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
91                  return False;                  return False;
# Line 98  wave_out_format_supported(WAVEFORMATEX * Line 98  wave_out_format_supported(WAVEFORMATEX *
98  }  }
99    
100  BOOL  BOOL
101  wave_out_set_format(WAVEFORMATEX *pwfx)  wave_out_set_format(WAVEFORMATEX * pwfx)
102  {  {
103          audio_info_t info;          audio_info_t info;
         int test = 1;  
104    
105          ioctl(g_dsp_fd, AUDIO_DRAIN, 0);          ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
106          swapaudio = False;          g_swapaudio = False;
107          AUDIO_INITINFO(&info);          AUDIO_INITINFO(&info);
108    
109    
110          if (pwfx->wBitsPerSample == 8)          if (pwfx->wBitsPerSample == 8)
111          {          {
112                  info.play.encoding = AUDIO_ENCODING_LINEAR8;                  info.play.encoding = AUDIO_ENCODING_LINEAR8;
                 samplewidth = 1;  
113          }          }
114          else if (pwfx->wBitsPerSample == 16)          else if (pwfx->wBitsPerSample == 16)
115          {          {
116                  info.play.encoding = AUDIO_ENCODING_LINEAR;                  info.play.encoding = AUDIO_ENCODING_LINEAR;
                 samplewidth = 2;  
117                  /* Do we need to swap the 16bit values? (Are we BigEndian) */                  /* Do we need to swap the 16bit values? (Are we BigEndian) */
118                  swapaudio = !(*(uint8 *) (&test));  #ifdef B_ENDIAN
119                    g_swapaudio = 1;
120    #else
121                    g_swapaudio = 0;
122    #endif
123          }          }
124    
125          if (pwfx->nChannels == 1 )          g_samplewidth = pwfx->wBitsPerSample / 8;
126          {        
127                  info.play.channels = AUDIO_CHANNELS_MONO;          if (pwfx->nChannels == 1)
128            {
129                    info.play.channels = 1;
130          }          }
131          else if (pwfx->nChannels == 2 )          else if (pwfx->nChannels == 2)
132          {          {
133                  info.play.channels = AUDIO_CHANNELS_STEREO;                  info.play.channels = 2;
134                  samplewidth *= 2;                  g_samplewidth *= 2;
135          }          }
136    
137          info.play.sample_rate = pwfx->nSamplesPerSec;          info.play.sample_rate = pwfx->nSamplesPerSec;
# Line 136  wave_out_set_format(WAVEFORMATEX *pwfx) Line 139  wave_out_set_format(WAVEFORMATEX *pwfx)
139          info.play.samples = 0;          info.play.samples = 0;
140          info.play.eof = 0;          info.play.eof = 0;
141          info.play.error = 0;          info.play.error = 0;
142            g_reopened = True;
143    
144          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
145          {          {
# Line 148  wave_out_set_format(WAVEFORMATEX *pwfx) Line 152  wave_out_set_format(WAVEFORMATEX *pwfx)
152  }  }
153    
154  void  void
155  wave_out_write(STREAM s, uint16 tick, uint8 index)  wave_out_volume(uint16 left, uint16 right)
156  {  {
157          struct audio_packet *packet = &packet_queue[queue_hi];          audio_info_t info;
158          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          uint balance;
159            uint volume;
160    
161            AUDIO_INITINFO(&info);
162    
163            volume = (left > right) ? left : right;
164    
165          if (next_hi == queue_lo)          if (volume / AUDIO_MID_BALANCE != 0)
166          {          {
167                  error("No space to queue audio packet\n");                  balance =
168                  return;                          AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
169                            (right / (volume / AUDIO_MID_BALANCE));
170            }
171            else
172            {
173                    balance = AUDIO_MID_BALANCE;
174          }          }
           
         queue_hi = next_hi;  
   
         packet->s = *s;  
         packet->tick = tick;  
         packet->index = index;  
175    
176          /* we steal the data buffer from s, give it a new one */          info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
177          s->data = malloc(s->size);          info.play.balance = balance;
178    
179          if (!g_dsp_busy)          if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
180                  wave_out_play();          {
181                    perror("AUDIO_SETINFO");
182                    return;
183            }
184  }  }
185    
186  void  void
# Line 188  wave_out_play(void) Line 199  wave_out_play(void)
199    
200          while (1)          while (1)
201          {          {
202                  if ( reopened )                  if (g_reopened)
203                  {                  {
204                          /* Device was just (re)openend */                          /* Device was just (re)openend */
205                          samplecnt = 0;                          samplecnt = 0;
206                          swapped = False;                          swapped = False;
207                          sentcompletion = True;                          sentcompletion = True;
208                          reopened = False;                          g_reopened = False;
209                  }                  }
210    
211                  if (queue_lo == queue_hi)                  if (rdpsnd_queue_empty())
212                  {                  {
213                          g_dsp_busy = 0;                          g_dsp_busy = 0;
214                          return;                          return;
215                  }                  }
216    
217                  packet = &packet_queue[queue_lo];                  packet = rdpsnd_queue_current_packet();
218                  out = &packet->s;                  out = &packet->s;
219    
220                  /* Swap the current packet, but only once */                  /* Swap the current packet, but only once */
221                  if ( swapaudio && ! swapped )                  if (g_swapaudio && !swapped)
222                  {                  {
223                          for ( i = 0; i < out->end - out->p; i+=2 )                          for (i = 0; i < out->end - out->p; i += 2)
224                          {                          {
225                                  swap = *(out->p + i);                                  swap = *(out->p + i);
226                                  *(out->p + i ) = *(out->p + i + 1);                                  *(out->p + i) = *(out->p + i + 1);
227                                  *(out->p + i + 1) = swap;                                  *(out->p + i + 1) = swap;
                                 swapped = True;  
228                          }                          }
229                            swapped = True;
230                  }                  }
231    
232                  if ( sentcompletion )                  if (sentcompletion)
233                  {                  {
234                          sentcompletion = False;                          sentcompletion = False;
235                          numsamples = (out->end - out->p)/samplewidth;                          numsamples = (out->end - out->p) / g_samplewidth;
236                  }                  }
237    
238                  len=0;                  len = 0;
239    
240                  if ( out->end != out->p )                  if (out->end != out->p)
241                  {                  {
242                          len = write(g_dsp_fd, out->p, out->end - out->p);                          len = write(g_dsp_fd, out->p, out->end - out->p);
243                          if (len == -1)                          if (len == -1)
# Line 248  wave_out_play(void) Line 259  wave_out_play(void)
259                          }                          }
260    
261                          /* Ack the packet, if we have played at least 70% */                          /* Ack the packet, if we have played at least 70% */
262                          if ( info.play.samples >= samplecnt+((numsamples*7)/10) )                          if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
263                          {                          {
264                                  samplecnt += numsamples;                                  samplecnt += numsamples;
265                                  rdpsnd_send_completion(packet->tick, packet->index);                                  /* We need to add 50 to tell windows that time has passed while
266                                  free(out->data);                                   * playing this packet */
267                                  queue_lo = (queue_lo + 1) % MAX_QUEUE;                                  rdpsnd_send_completion(packet->tick + 50, packet->index);
268                                    rdpsnd_queue_next();
269                                  swapped = False;                                  swapped = False;
270                                  sentcompletion = True;                                  sentcompletion = True;
271                          }                          }

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

  ViewVC Help
Powered by ViewVC 1.1.26