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

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

revision 1254 by stargo, Sun Sep 17 10:32:18 2006 UTC revision 1356 by ossman_, Tue Jan 2 11:39:56 2007 UTC
# Line 22  Line 22 
22    
23  #include "rdesktop.h"  #include "rdesktop.h"
24  #include "rdpsnd.h"  #include "rdpsnd.h"
25    #include "rdpsnd_dsp.h"
26  #include <unistd.h>  #include <unistd.h>
27  #include <fcntl.h>  #include <fcntl.h>
28  #include <errno.h>  #include <errno.h>
# Line 31  Line 32 
32  #define DEFAULTDEVICE   "default"  #define DEFAULTDEVICE   "default"
33  #define MAX_FRAMES      32  #define MAX_FRAMES      32
34    
35    static struct pollfd pfds[32];
36    static int num_fds;
37    
38  static snd_pcm_t *pcm_handle = NULL;  static snd_pcm_t *pcm_handle = NULL;
39  static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;  static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
40  static BOOL reopened;  static BOOL reopened;
41  static short samplewidth;  static short samplewidth;
42  static int audiochannels;  static int audiochannels;
43    static unsigned int rate;
44    static char *pcm_name;
45    
46  BOOL  void alsa_play(void);
47  wave_out_open(void)  
48    void
49    alsa_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
50  {  {
         char *pcm_name;  
51          int err;          int err;
52            struct pollfd *f;
53    
54            if (!pcm_handle)
55                    return;
56    
57            if (rdpsnd_queue_empty())
58                    return;
59    
60            num_fds = snd_pcm_poll_descriptors_count(pcm_handle);
61    
62            if (num_fds > sizeof(pfds) / sizeof(*pfds))
63                    return;
64    
65            err = snd_pcm_poll_descriptors(pcm_handle, pfds, num_fds);
66            if (err < 0)
67                    return;
68    
69            for (f = pfds; f < &pfds[num_fds]; f++)
70            {
71                    if (f->events & POLLIN)
72                            FD_SET(f->fd, rfds);
73                    if (f->events & POLLOUT)
74                            FD_SET(f->fd, wfds);
75                    if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
76                            *n = f->fd;
77            }
78    }
79    
80    void
81    alsa_check_fds(fd_set * rfds, fd_set * wfds)
82    {
83            struct pollfd *f;
84            int err;
85            unsigned short revents;
86    
87            if (!pcm_handle)
88                    return;
89    
90            for (f = pfds; f < &pfds[num_fds]; f++)
91            {
92                    f->revents = 0;
93                    if (f->fd != -1)
94                    {
95                            /* Fixme: This doesn't properly deal with things like POLLHUP */
96                            if (FD_ISSET(f->fd, rfds))
97                                    f->revents |= POLLIN;
98                            if (FD_ISSET(f->fd, wfds))
99                                    f->revents |= POLLOUT;
100                    }
101            }
102    
103            err = snd_pcm_poll_descriptors_revents(pcm_handle, pfds, num_fds, &revents);
104            if (err < 0)
105                    return;
106    
107            if (revents & POLLOUT)
108                    alsa_play();
109    }
110    
111          pcm_name = xstrdup(DEFAULTDEVICE);  BOOL
112    alsa_open(void)
113    {
114            int err;
115    
116          if ((err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0)) < 0)          if ((err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0)) < 0)
117          {          {
# Line 51  wave_out_open(void) Line 119  wave_out_open(void)
119                  return False;                  return False;
120          }          }
121    
         g_dsp_fd = 0;  
         rdpsnd_queue_init();  
   
122          reopened = True;          reopened = True;
123    
124          return True;          return True;
125  }  }
126    
127  void  void
128  wave_out_close(void)  alsa_close(void)
129  {  {
130          /* Ack all remaining packets */          /* Ack all remaining packets */
131          while (!rdpsnd_queue_empty())          while (!rdpsnd_queue_empty())
132          {                  rdpsnd_queue_next(0);
                 rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,  
                                        rdpsnd_queue_current_packet()->index);  
                 rdpsnd_queue_next();  
         }  
   
133    
134          if (pcm_handle)          if (pcm_handle)
135          {          {
                 snd_pcm_drop(pcm_handle);  
136                  snd_pcm_close(pcm_handle);                  snd_pcm_close(pcm_handle);
137                    pcm_handle = NULL;
138          }          }
139  }  }
140    
141  BOOL  BOOL
142  wave_out_format_supported(WAVEFORMATEX * pwfx)  alsa_format_supported(WAVEFORMATEX * pwfx)
143  {  {
144  #if 0  #if 0
145          int err;          int err;
# Line 112  wave_out_format_supported(WAVEFORMATEX * Line 172  wave_out_format_supported(WAVEFORMATEX *
172  }  }
173    
174  BOOL  BOOL
175  wave_out_set_format(WAVEFORMATEX * pwfx)  alsa_set_format(WAVEFORMATEX * pwfx)
176  {  {
177          snd_pcm_hw_params_t *hwparams = NULL;          snd_pcm_hw_params_t *hwparams = NULL;
         unsigned int rate, exact_rate;  
178          int err;          int err;
179          unsigned int buffertime;          unsigned int buffertime;
180    
# Line 167  wave_out_set_format(WAVEFORMATEX * pwfx) Line 226  wave_out_set_format(WAVEFORMATEX * pwfx)
226          }          }
227  #endif  #endif
228    
229          exact_rate = rate = pwfx->nSamplesPerSec;          rate = pwfx->nSamplesPerSec;
230          if ((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0)) < 0)          if ((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0)) < 0)
231          {          {
232                  error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err));                  error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err));
233                  return False;                  return False;
# Line 210  wave_out_set_format(WAVEFORMATEX * pwfx) Line 269  wave_out_set_format(WAVEFORMATEX * pwfx)
269  }  }
270    
271  void  void
272  wave_out_volume(uint16 left, uint16 right)  alsa_play(void)
 {  
         static int warned = 0;  
   
         if (!warned)  
         {  
                 warning("volume changes currently not supported with experimental alsa-output\n");  
                 warned = 1;  
         }  
 }  
   
 void  
 wave_out_play(void)  
273  {  {
274          struct audio_packet *packet;          struct audio_packet *packet;
275          STREAM out;          STREAM out;
# Line 240  wave_out_play(void) Line 287  wave_out_play(void)
287                  prev_us = tv.tv_usec;                  prev_us = tv.tv_usec;
288          }          }
289    
290            /* We shouldn't be called if the queue is empty, but still */
291          if (rdpsnd_queue_empty())          if (rdpsnd_queue_empty())
         {  
                 g_dsp_busy = 0;  
292                  return;                  return;
         }  
293    
294          packet = rdpsnd_queue_current_packet();          packet = rdpsnd_queue_current_packet();
295          out = &packet->s;          out = &packet->s;
# Line 268  wave_out_play(void) Line 313  wave_out_play(void)
313    
314          if ((out->p == out->end) || duration > next_tick - packet->tick + 500)          if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
315          {          {
316                    snd_pcm_sframes_t delay_frames;
317                    unsigned long delay_us;
318    
319                  prev_s = tv.tv_sec;                  prev_s = tv.tv_sec;
320                  prev_us = tv.tv_usec;                  prev_us = tv.tv_usec;
321    
# Line 278  wave_out_play(void) Line 326  wave_out_play(void)
326                                 (packet->tick + duration) % 65536, next_tick % 65536));                                 (packet->tick + duration) % 65536, next_tick % 65536));
327                  }                  }
328    
329                  rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);                  if (snd_pcm_delay(pcm_handle, &delay_frames) < 0)
330                  rdpsnd_queue_next();                          delay_frames = out->size / (samplewidth * audiochannels);
331                    if (delay_frames < 0)
332                            delay_frames = 0;
333    
334                    delay_us = delay_frames * (1000000 / rate);
335    
336                    rdpsnd_queue_next(delay_us);
337            }
338    }
339    
340    struct audio_driver *
341    alsa_register(char *options)
342    {
343            static struct audio_driver alsa_driver;
344    
345            memset(&alsa_driver, 0, sizeof(alsa_driver));
346    
347            alsa_driver.name = "alsa";
348            alsa_driver.description = "ALSA output driver, default device: " DEFAULTDEVICE;
349    
350            alsa_driver.add_fds = alsa_add_fds;
351            alsa_driver.check_fds = alsa_check_fds;
352    
353            alsa_driver.wave_out_open = alsa_open;
354            alsa_driver.wave_out_close = alsa_close;
355            alsa_driver.wave_out_format_supported = alsa_format_supported;
356            alsa_driver.wave_out_set_format = alsa_set_format;
357            alsa_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
358    
359            alsa_driver.need_byteswap_on_be = 0;
360            alsa_driver.need_resampling = 0;
361    
362            if (options)
363            {
364                    pcm_name = xstrdup(options);
365            }
366            else
367            {
368                    pcm_name = DEFAULTDEVICE;
369          }          }
370    
371          g_dsp_busy = 1;          return &alsa_driver;
         return;  
372  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26