/[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 1255 by stargo, Sun Sep 17 11:04:50 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;  static char *pcm_name;
45    
46    void alsa_play(void);
47    
48    void
49    alsa_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
50    {
51            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  BOOL  BOOL
112  alsa_open(void)  alsa_open(void)
113  {  {
# Line 49  alsa_open(void) Line 119  alsa_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;
# Line 62  alsa_close(void) Line 129  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    
# Line 112  BOOL Line 175  BOOL
175  alsa_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 164  alsa_set_format(WAVEFORMATEX * pwfx) Line 226  alsa_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 207  alsa_set_format(WAVEFORMATEX * pwfx) Line 269  alsa_set_format(WAVEFORMATEX * pwfx)
269  }  }
270    
271  void  void
 alsa_volume(uint16 left, uint16 right)  
 {  
         static int warned = 0;  
   
         if (!warned)  
         {  
                 warning("volume changes currently not supported with alsa-output\n");  
                 warned = 1;  
         }  
 }  
   
 void  
272  alsa_play(void)  alsa_play(void)
273  {  {
274          struct audio_packet *packet;          struct audio_packet *packet;
# Line 237  alsa_play(void) Line 287  alsa_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 265  alsa_play(void) Line 313  alsa_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 275  alsa_play(void) Line 326  alsa_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          g_dsp_busy = 1;                  delay_us = delay_frames * (1000000 / rate);
         return;  
 }  
335    
336  static struct audio_driver alsa_driver = {                  rdpsnd_queue_next(delay_us);
337        wave_out_write:rdpsnd_queue_write,          }
338        wave_out_open:alsa_open,  }
       wave_out_close:alsa_close,  
       wave_out_format_supported:alsa_format_supported,  
       wave_out_set_format:alsa_set_format,  
       wave_out_volume:alsa_volume,  
       wave_out_play:alsa_play,  
       name:"alsa",  
       description:"ALSA output driver, default device: " DEFAULTDEVICE,  
       next:NULL,  
 };  
339    
340  struct audio_driver *  struct audio_driver *
341  alsa_register(char *options)  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)          if (options)
363          {          {
364                  pcm_name = xstrdup(options);                  pcm_name = xstrdup(options);
365          }          }
366          else          else
367          {          {
368                  pcm_name = xstrdup(DEFAULTDEVICE);                  pcm_name = DEFAULTDEVICE;
369          }          }
370    
371          return &alsa_driver;          return &alsa_driver;

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

  ViewVC Help
Powered by ViewVC 1.1.26