Imported Upstream version 3.2.2
[debian/gnuradio] / gr-audio-alsa / src / audio_alsa_sink.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <audio_alsa_sink.h>
28 #include <gr_io_signature.h>
29 #include <gr_prefs.h>
30 #include <stdio.h>
31 #include <iostream>
32 #include <stdexcept>
33 #include <gri_alsa.h>
34
35
36 static bool CHATTY_DEBUG = false;
37
38
39 static snd_pcm_format_t acceptable_formats[] = {
40   // these are in our preferred order...
41   SND_PCM_FORMAT_S32,
42   SND_PCM_FORMAT_S16
43 };
44
45 #define NELEMS(x) (sizeof(x)/sizeof(x[0]))
46
47
48 static std::string 
49 default_device_name ()
50 {
51   return gr_prefs::singleton()->get_string("audio_alsa", "default_output_device", "hw:0,0");
52 }
53
54 static double
55 default_period_time ()
56 {
57   return std::max(0.001, gr_prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
58 }
59
60 static int
61 default_nperiods ()
62 {
63   return std::max(2L, gr_prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
64 }
65
66 // ----------------------------------------------------------------
67
68 audio_alsa_sink_sptr
69 audio_alsa_make_sink (int sampling_rate,
70                       const std::string dev,
71                       bool ok_to_block)
72 {
73   return audio_alsa_sink_sptr (new audio_alsa_sink (sampling_rate, dev,
74                                                     ok_to_block));
75 }
76
77 audio_alsa_sink::audio_alsa_sink (int sampling_rate,
78                                   const std::string device_name,
79                                   bool ok_to_block)
80   : gr_sync_block ("audio_alsa_sink",
81                    gr_make_io_signature (0, 0, 0),
82                    gr_make_io_signature (0, 0, 0)),
83     d_sampling_rate (sampling_rate),
84     d_device_name (device_name.empty() ? default_device_name() : device_name),
85     d_pcm_handle (0),
86     d_hw_params ((snd_pcm_hw_params_t *)(new char[snd_pcm_hw_params_sizeof()])),
87     d_sw_params ((snd_pcm_sw_params_t *)(new char[snd_pcm_sw_params_sizeof()])),
88     d_nperiods (default_nperiods()),
89     d_period_time_us ((unsigned int) (default_period_time() * 1e6)),
90     d_period_size (0),
91     d_buffer_size_bytes (0), d_buffer (0),
92     d_worker (0), d_special_case_mono_to_stereo (false),
93     d_nunderuns (0), d_nsuspends (0)
94 {
95   CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false);
96
97   int   error;
98   int   dir;
99
100   // open the device for playback
101   error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (),
102                        SND_PCM_STREAM_PLAYBACK, 0);
103   if (error < 0){
104     fprintf (stderr, "audio_alsa_sink[%s]: %s\n",
105              d_device_name.c_str(), snd_strerror(error));
106     throw std::runtime_error ("audio_alsa_sink");
107   }
108
109   // Fill params with a full configuration space for a PCM.
110   error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
111   if (error < 0)
112     bail ("broken configuration for playback", error);
113
114
115   if (CHATTY_DEBUG)
116     gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout);
117
118
119   // now that we know how many channels the h/w can handle, set input signature
120   unsigned int umin_chan, umax_chan;
121   snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan);
122   snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan);
123   int min_chan = std::min (umin_chan, 1000U);
124   int max_chan = std::min (umax_chan, 1000U);
125
126   // As a special case, if the hw's min_chan is two, we'll accept
127   // a single input and handle the duplication ourselves.
128
129   if (min_chan == 2){
130     min_chan = 1;
131     d_special_case_mono_to_stereo = true;
132   }
133   set_input_signature (gr_make_io_signature (min_chan, max_chan,
134                                              sizeof (float)));
135   
136   // fill in portions of the d_hw_params that we know now...
137
138   // Specify the access methods we implement
139   // For now, we only handle RW_INTERLEAVED...
140   snd_pcm_access_mask_t *access_mask;
141   snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
142   snd_pcm_access_mask_alloca (access_mask_ptr);
143   snd_pcm_access_mask_none (access_mask);
144   snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
145   // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
146
147   if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle,
148                                                   d_hw_params, access_mask)) < 0)
149     bail ("failed to set access mask", error);
150
151
152   // set sample format
153   if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params,
154                                         acceptable_formats,
155                                         NELEMS (acceptable_formats),
156                                         &d_format,
157                                         "audio_alsa_sink",
158                                         CHATTY_DEBUG))
159     throw std::runtime_error ("audio_alsa_sink");
160   
161
162   // sampling rate
163   unsigned int orig_sampling_rate = d_sampling_rate;
164   if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params,
165                                                 &d_sampling_rate, 0)) < 0)
166     bail ("failed to set rate near", error);
167   
168   if (orig_sampling_rate != d_sampling_rate){
169     fprintf (stderr, "audio_alsa_sink[%s]: unable to support sampling rate %d\n",
170              snd_pcm_name (d_pcm_handle), orig_sampling_rate);
171     fprintf (stderr, "  card requested %d instead.\n", d_sampling_rate);
172   }
173
174   /*
175    * ALSA transfers data in units of "periods".
176    * We indirectly determine the underlying buffersize by specifying
177    * the number of periods we want (typically 4) and the length of each
178    * period in units of time (typically 1ms).
179    */
180   unsigned int min_nperiods, max_nperiods;
181   snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir);
182   snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir);
183   //fprintf (stderr, "alsa_sink: min_nperiods = %d, max_nperiods = %d\n",
184   // min_nperiods, max_nperiods);
185
186   unsigned int orig_nperiods = d_nperiods;
187   d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods);
188
189   // adjust period time so that total buffering remains more-or-less constant
190   d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
191
192   error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params,
193                                          d_nperiods, 0);
194   if (error < 0)
195     bail ("set_periods failed", error);
196
197   dir = 0;
198   error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params,
199                                                   &d_period_time_us, &dir);
200   if (error < 0)
201     bail ("set_period_time_near failed", error);
202
203   dir = 0;
204   error = snd_pcm_hw_params_get_period_size (d_hw_params,
205                                              &d_period_size, &dir);
206   if (error < 0)
207     bail ("get_period_size failed", error);
208   
209   set_output_multiple (d_period_size);
210 }
211
212
213 bool
214 audio_alsa_sink::check_topology (int ninputs, int noutputs)
215 {
216   // ninputs is how many channels the user has connected.
217   // Now we can finish up setting up the hw params...
218
219   int nchan = ninputs;
220   int err;
221
222   // FIXME check_topology may be called more than once.
223   // Ensure that the pcm is in a state where we can still mess with the hw_params
224
225   bool special_case = nchan == 1 && d_special_case_mono_to_stereo;
226   if (special_case)
227     nchan = 2;
228   
229   err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, nchan);
230
231   if (err < 0){
232     output_error_msg ("set_channels failed", err);
233     return false;
234   }
235
236   // set the parameters into the driver...
237   err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
238   if (err < 0){
239     output_error_msg ("snd_pcm_hw_params failed", err);
240     return false;
241   }
242
243   // get current s/w params
244   err = snd_pcm_sw_params_current (d_pcm_handle, d_sw_params);
245   if (err < 0)
246     bail ("snd_pcm_sw_params_current", err);
247   
248   // Tell the PCM device to wait to start until we've filled
249   // it's buffers half way full.  This helps avoid audio underruns.
250
251   err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle,
252                                               d_sw_params,
253                                               d_nperiods * d_period_size / 2);
254   if (err < 0)
255     bail ("snd_pcm_sw_params_set_start_threshold", err);
256
257   // store the s/w params
258   err = snd_pcm_sw_params (d_pcm_handle, d_sw_params);
259   if (err < 0)
260     bail ("snd_pcm_sw_params", err);
261
262   d_buffer_size_bytes =
263     d_period_size * nchan * snd_pcm_format_size (d_format, 1);
264
265   d_buffer = new char [d_buffer_size_bytes];
266
267   if (CHATTY_DEBUG)
268     fprintf (stdout, "audio_alsa_sink[%s]: sample resolution = %d bits\n",
269              snd_pcm_name (d_pcm_handle),
270              snd_pcm_hw_params_get_sbits (d_hw_params));
271
272   switch (d_format){
273   case SND_PCM_FORMAT_S16:
274     if (special_case)
275       d_worker = &audio_alsa_sink::work_s16_1x2;
276     else
277       d_worker = &audio_alsa_sink::work_s16;
278     break;
279
280   case SND_PCM_FORMAT_S32:
281     if (special_case)
282       d_worker = &audio_alsa_sink::work_s32_1x2;
283     else
284       d_worker = &audio_alsa_sink::work_s32;
285     break;
286
287   default:
288     assert (0);
289   }
290
291   return true;
292 }
293
294 audio_alsa_sink::~audio_alsa_sink ()
295 {
296   if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING)
297     snd_pcm_drop (d_pcm_handle);
298
299   snd_pcm_close(d_pcm_handle);
300   delete [] ((char *) d_hw_params);
301   delete [] ((char *) d_sw_params);
302   delete [] d_buffer;
303 }
304
305 int
306 audio_alsa_sink::work (int noutput_items,
307                        gr_vector_const_void_star &input_items,
308                        gr_vector_void_star &output_items)
309 {
310   assert ((noutput_items % d_period_size) == 0);
311
312   // this is a call through a pointer to a method...
313   return (this->*d_worker)(noutput_items, input_items, output_items);
314 }
315
316 /*
317  * Work function that deals with float to S16 conversion
318  */
319 int
320 audio_alsa_sink::work_s16 (int noutput_items,
321                            gr_vector_const_void_star &input_items,
322                            gr_vector_void_star &output_items)
323 {
324   typedef gr_int16      sample_t;       // the type of samples we're creating
325   static const int NBITS = 16;          // # of bits in a sample
326   
327   unsigned int nchan = input_items.size ();
328   const float **in = (const float **) &input_items[0];
329   sample_t *buf = (sample_t *) d_buffer;
330   int bi;
331   int n;
332
333   unsigned int sizeof_frame = nchan * sizeof (sample_t);
334   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
335
336   for (n = 0; n < noutput_items; n += d_period_size){
337
338     // process one period of data
339     bi = 0;
340     for (unsigned int i = 0; i < d_period_size; i++){
341       for (unsigned int chan = 0; chan < nchan; chan++){
342         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
343       }
344     }
345
346     // update src pointers
347     for (unsigned int chan = 0; chan < nchan; chan++)
348       in[chan] += d_period_size;
349
350     if (!write_buffer (buf, d_period_size, sizeof_frame))  
351       return -1;        // No fixing this problem.  Say we're done.
352   }
353
354   return n;
355 }
356
357
358 /*
359  * Work function that deals with float to S32 conversion
360  */
361 int
362 audio_alsa_sink::work_s32 (int noutput_items,
363                            gr_vector_const_void_star &input_items,
364                            gr_vector_void_star &output_items)
365 {
366   typedef gr_int32      sample_t;       // the type of samples we're creating
367   static const int NBITS = 32;          // # of bits in a sample
368   
369   unsigned int nchan = input_items.size ();
370   const float **in = (const float **) &input_items[0];
371   sample_t *buf = (sample_t *) d_buffer;
372   int bi;
373   int n;
374
375   unsigned int sizeof_frame = nchan * sizeof (sample_t);
376   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
377
378   for (n = 0; n < noutput_items; n += d_period_size){
379
380     // process one period of data
381     bi = 0;
382     for (unsigned int i = 0; i < d_period_size; i++){
383       for (unsigned int chan = 0; chan < nchan; chan++){
384         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
385       }
386     }
387
388     // update src pointers
389     for (unsigned int chan = 0; chan < nchan; chan++)
390       in[chan] += d_period_size;
391
392     if (!write_buffer (buf, d_period_size, sizeof_frame))  
393       return -1;        // No fixing this problem.  Say we're done.
394   }
395
396   return n;
397 }
398
399 /*
400  * Work function that deals with float to S16 conversion and
401  * mono to stereo kludge.
402  */
403 int
404 audio_alsa_sink::work_s16_1x2 (int noutput_items,
405                                gr_vector_const_void_star &input_items,
406                                gr_vector_void_star &output_items)
407 {
408   typedef gr_int16      sample_t;       // the type of samples we're creating
409   static const int NBITS = 16;          // # of bits in a sample
410   
411   assert (input_items.size () == 1);
412   static const unsigned int nchan = 2;
413   const float **in = (const float **) &input_items[0];
414   sample_t *buf = (sample_t *) d_buffer;
415   int bi;
416   int n;
417
418   unsigned int sizeof_frame = nchan * sizeof (sample_t);
419   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
420
421   for (n = 0; n < noutput_items; n += d_period_size){
422
423     // process one period of data
424     bi = 0;
425     for (unsigned int i = 0; i < d_period_size; i++){
426       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
427       buf[bi++] = t;
428       buf[bi++] = t;
429     }
430
431     // update src pointers
432     in[0] += d_period_size;
433
434     if (!write_buffer (buf, d_period_size, sizeof_frame))  
435       return -1;        // No fixing this problem.  Say we're done.
436   }
437
438   return n;
439 }
440
441 /*
442  * Work function that deals with float to S32 conversion and
443  * mono to stereo kludge.
444  */
445 int
446 audio_alsa_sink::work_s32_1x2 (int noutput_items,
447                                gr_vector_const_void_star &input_items,
448                                gr_vector_void_star &output_items)
449 {
450   typedef gr_int32      sample_t;       // the type of samples we're creating
451   static const int NBITS = 32;          // # of bits in a sample
452   
453   assert (input_items.size () == 1);
454   static unsigned int nchan = 2;
455   const float **in = (const float **) &input_items[0];
456   sample_t *buf = (sample_t *) d_buffer;
457   int bi;
458   int n;
459
460   unsigned int sizeof_frame = nchan * sizeof (sample_t);
461   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
462
463   for (n = 0; n < noutput_items; n += d_period_size){
464
465     // process one period of data
466     bi = 0;
467     for (unsigned int i = 0; i < d_period_size; i++){
468       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
469       buf[bi++] = t;
470       buf[bi++] = t;
471     }
472
473     // update src pointers
474     in[0] += d_period_size;
475
476     if (!write_buffer (buf, d_period_size, sizeof_frame))  
477       return -1;        // No fixing this problem.  Say we're done.
478   }
479
480   return n;
481 }
482
483 bool
484 audio_alsa_sink::write_buffer (const void *vbuffer,
485                                unsigned nframes, unsigned sizeof_frame)
486 {
487   const unsigned char *buffer = (const unsigned char *) vbuffer;
488
489   while (nframes > 0){
490     int r = snd_pcm_writei (d_pcm_handle, buffer, nframes);
491     if (r == -EAGAIN)
492       continue;                 // try again
493
494     else if (r == -EPIPE){      // underrun
495       d_nunderuns++;
496       fputs ("aU", stderr);
497       if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){
498         output_error_msg ("snd_pcm_prepare failed. Can't recover from underrun", r);
499         return false;
500       }
501       continue;                 // try again
502     }
503
504     else if (r == -ESTRPIPE){   // h/w is suspended (whatever that means)
505                                 // This is apparently related to power management
506       d_nsuspends++;
507       if ((r = snd_pcm_resume (d_pcm_handle)) < 0){
508         output_error_msg ("failed to resume from suspend", r);
509         return false;
510       }
511       continue;                 // try again
512     }
513
514     else if (r < 0){
515       output_error_msg ("snd_pcm_writei failed", r);
516       return false;
517     }
518
519     nframes -= r;
520     buffer += r * sizeof_frame;
521   }
522
523   return true;
524 }
525
526
527 void
528 audio_alsa_sink::output_error_msg (const char *msg, int err)
529 {
530   fprintf (stderr, "audio_alsa_sink[%s]: %s: %s\n",
531            snd_pcm_name (d_pcm_handle), msg,  snd_strerror (err));
532 }
533
534 void
535 audio_alsa_sink::bail (const char *msg, int err) throw (std::runtime_error)
536 {
537   output_error_msg (msg, err);
538   throw std::runtime_error ("audio_alsa_sink");
539 }