Reverting last change in alsa.
[debian/gnuradio] / gr-audio-alsa / src / audio_alsa_sink.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2010 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 gnuradio::get_initial_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), d_ok_to_block(ok_to_block)
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 (ok_to_block == false)
104     snd_pcm_nonblock(d_pcm_handle, !ok_to_block);
105   if (error < 0){
106     fprintf (stderr, "audio_alsa_sink[%s]: %s\n",
107              d_device_name.c_str(), snd_strerror(error));
108     throw std::runtime_error ("audio_alsa_sink");
109   }
110
111   // Fill params with a full configuration space for a PCM.
112   error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
113   if (error < 0)
114     bail ("broken configuration for playback", error);
115
116
117   if (CHATTY_DEBUG)
118     gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout);
119
120
121   // now that we know how many channels the h/w can handle, set input signature
122   unsigned int umin_chan, umax_chan;
123   snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan);
124   snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan);
125   int min_chan = std::min (umin_chan, 1000U);
126   int max_chan = std::min (umax_chan, 1000U);
127
128   // As a special case, if the hw's min_chan is two, we'll accept
129   // a single input and handle the duplication ourselves.
130
131   if (min_chan == 2){
132     min_chan = 1;
133     d_special_case_mono_to_stereo = true;
134   }
135   set_input_signature (gr_make_io_signature (min_chan, max_chan,
136                                              sizeof (float)));
137   
138   // fill in portions of the d_hw_params that we know now...
139
140   // Specify the access methods we implement
141   // For now, we only handle RW_INTERLEAVED...
142   snd_pcm_access_mask_t *access_mask;
143   snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
144   snd_pcm_access_mask_alloca (access_mask_ptr);
145   snd_pcm_access_mask_none (access_mask);
146   snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
147   // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
148
149   if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle,
150                                                   d_hw_params, access_mask)) < 0)
151     bail ("failed to set access mask", error);
152
153
154   // set sample format
155   if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params,
156                                         acceptable_formats,
157                                         NELEMS (acceptable_formats),
158                                         &d_format,
159                                         "audio_alsa_sink",
160                                         CHATTY_DEBUG))
161     throw std::runtime_error ("audio_alsa_sink");
162   
163
164   // sampling rate
165   unsigned int orig_sampling_rate = d_sampling_rate;
166   if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params,
167                                                 &d_sampling_rate, 0)) < 0)
168     bail ("failed to set rate near", error);
169   
170   if (orig_sampling_rate != d_sampling_rate){
171     fprintf (stderr, "audio_alsa_sink[%s]: unable to support sampling rate %d\n",
172              snd_pcm_name (d_pcm_handle), orig_sampling_rate);
173     fprintf (stderr, "  card requested %d instead.\n", d_sampling_rate);
174   }
175
176   /*
177    * ALSA transfers data in units of "periods".
178    * We indirectly determine the underlying buffersize by specifying
179    * the number of periods we want (typically 4) and the length of each
180    * period in units of time (typically 1ms).
181    */
182   unsigned int min_nperiods, max_nperiods;
183   snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir);
184   snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir);
185   //fprintf (stderr, "alsa_sink: min_nperiods = %d, max_nperiods = %d\n",
186   // min_nperiods, max_nperiods);
187
188   unsigned int orig_nperiods = d_nperiods;
189   d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods);
190
191   // adjust period time so that total buffering remains more-or-less constant
192   d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
193
194   error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params,
195                                          d_nperiods, 0);
196   if (error < 0)
197     bail ("set_periods failed", error);
198
199   dir = 0;
200   error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params,
201                                                   &d_period_time_us, &dir);
202   if (error < 0)
203     bail ("set_period_time_near failed", error);
204
205   dir = 0;
206   error = snd_pcm_hw_params_get_period_size (d_hw_params,
207                                              &d_period_size, &dir);
208   if (error < 0)
209     bail ("get_period_size failed", error);
210   
211   set_output_multiple (d_period_size);
212 }
213
214
215 bool
216 audio_alsa_sink::check_topology (int ninputs, int noutputs)
217 {
218   // ninputs is how many channels the user has connected.
219   // Now we can finish up setting up the hw params...
220
221   int nchan = ninputs;
222   int err;
223
224   // FIXME check_topology may be called more than once.
225   // Ensure that the pcm is in a state where we can still mess with the hw_params
226
227   bool special_case = nchan == 1 && d_special_case_mono_to_stereo;
228   if (special_case)
229     nchan = 2;
230   
231   err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, nchan);
232
233   if (err < 0){
234     output_error_msg ("set_channels failed", err);
235     return false;
236   }
237
238   // set the parameters into the driver...
239   err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
240   if (err < 0){
241     output_error_msg ("snd_pcm_hw_params failed", err);
242     return false;
243   }
244
245   // get current s/w params
246   err = snd_pcm_sw_params_current (d_pcm_handle, d_sw_params);
247   if (err < 0)
248     bail ("snd_pcm_sw_params_current", err);
249   
250   // Tell the PCM device to wait to start until we've filled
251   // it's buffers half way full.  This helps avoid audio underruns.
252
253   err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle,
254                                               d_sw_params,
255                                               d_nperiods * d_period_size / 2);
256   if (err < 0)
257     bail ("snd_pcm_sw_params_set_start_threshold", err);
258
259   // store the s/w params
260   err = snd_pcm_sw_params (d_pcm_handle, d_sw_params);
261   if (err < 0)
262     bail ("snd_pcm_sw_params", err);
263
264   d_buffer_size_bytes =
265     d_period_size * nchan * snd_pcm_format_size (d_format, 1);
266
267   d_buffer = new char [d_buffer_size_bytes];
268
269   if (CHATTY_DEBUG)
270     fprintf (stdout, "audio_alsa_sink[%s]: sample resolution = %d bits\n",
271              snd_pcm_name (d_pcm_handle),
272              snd_pcm_hw_params_get_sbits (d_hw_params));
273
274   switch (d_format){
275   case SND_PCM_FORMAT_S16:
276     if (special_case)
277       d_worker = &audio_alsa_sink::work_s16_1x2;
278     else
279       d_worker = &audio_alsa_sink::work_s16;
280     break;
281
282   case SND_PCM_FORMAT_S32:
283     if (special_case)
284       d_worker = &audio_alsa_sink::work_s32_1x2;
285     else
286       d_worker = &audio_alsa_sink::work_s32;
287     break;
288
289   default:
290     assert (0);
291   }
292   return true;
293 }
294
295 audio_alsa_sink::~audio_alsa_sink ()
296 {
297   if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING)
298     snd_pcm_drop (d_pcm_handle);
299
300   snd_pcm_close(d_pcm_handle);
301   delete [] ((char *) d_hw_params);
302   delete [] ((char *) d_sw_params);
303   delete [] d_buffer;
304 }
305
306 int
307 audio_alsa_sink::work (int noutput_items,
308                        gr_vector_const_void_star &input_items,
309                        gr_vector_void_star &output_items)
310 {
311   assert ((noutput_items % d_period_size) == 0);
312
313   // this is a call through a pointer to a method...
314   return (this->*d_worker)(noutput_items, input_items, output_items);
315 }
316
317 /*
318  * Work function that deals with float to S16 conversion
319  */
320 int
321 audio_alsa_sink::work_s16 (int noutput_items,
322                            gr_vector_const_void_star &input_items,
323                            gr_vector_void_star &output_items)
324 {
325   typedef gr_int16      sample_t;       // the type of samples we're creating
326   static const int NBITS = 16;          // # of bits in a sample
327   
328   unsigned int nchan = input_items.size ();
329   const float **in = (const float **) &input_items[0];
330   sample_t *buf = (sample_t *) d_buffer;
331   int bi;
332   int n;
333
334   unsigned int sizeof_frame = nchan * sizeof (sample_t);
335   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
336
337   for (n = 0; n < noutput_items; n += d_period_size){
338
339     // process one period of data
340     bi = 0;
341     for (unsigned int i = 0; i < d_period_size; i++){
342       for (unsigned int chan = 0; chan < nchan; chan++){
343         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
344       }
345     }
346
347     // update src pointers
348     for (unsigned int chan = 0; chan < nchan; chan++)
349       in[chan] += d_period_size;
350
351     if (!write_buffer (buf, d_period_size, sizeof_frame))  
352       return -1;        // No fixing this problem.  Say we're done.
353   }
354
355   return n;
356 }
357
358
359 /*
360  * Work function that deals with float to S32 conversion
361  */
362 int
363 audio_alsa_sink::work_s32 (int noutput_items,
364                            gr_vector_const_void_star &input_items,
365                            gr_vector_void_star &output_items)
366 {
367   typedef gr_int32      sample_t;       // the type of samples we're creating
368   static const int NBITS = 32;          // # of bits in a sample
369   
370   unsigned int nchan = input_items.size ();
371   const float **in = (const float **) &input_items[0];
372   sample_t *buf = (sample_t *) d_buffer;
373   int bi;
374   int n;
375
376   unsigned int sizeof_frame = nchan * sizeof (sample_t);
377   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
378
379   for (n = 0; n < noutput_items; n += d_period_size){
380
381     // process one period of data
382     bi = 0;
383     for (unsigned int i = 0; i < d_period_size; i++){
384       for (unsigned int chan = 0; chan < nchan; chan++){
385         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
386       }
387     }
388
389     // update src pointers
390     for (unsigned int chan = 0; chan < nchan; chan++)
391       in[chan] += d_period_size;
392
393     if (!write_buffer (buf, d_period_size, sizeof_frame))  
394       return -1;        // No fixing this problem.  Say we're done.
395   }
396
397   return n;
398 }
399
400 /*
401  * Work function that deals with float to S16 conversion and
402  * mono to stereo kludge.
403  */
404 int
405 audio_alsa_sink::work_s16_1x2 (int noutput_items,
406                                gr_vector_const_void_star &input_items,
407                                gr_vector_void_star &output_items)
408 {
409   typedef gr_int16      sample_t;       // the type of samples we're creating
410   static const int NBITS = 16;          // # of bits in a sample
411   
412   assert (input_items.size () == 1);
413   static const unsigned int nchan = 2;
414   const float **in = (const float **) &input_items[0];
415   sample_t *buf = (sample_t *) d_buffer;
416   int bi;
417   int n;
418
419   unsigned int sizeof_frame = nchan * sizeof (sample_t);
420   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
421
422   for (n = 0; n < noutput_items; n += d_period_size){
423
424     // process one period of data
425     bi = 0;
426     for (unsigned int i = 0; i < d_period_size; i++){
427       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
428       buf[bi++] = t;
429       buf[bi++] = t;
430     }
431
432     // update src pointers
433     in[0] += d_period_size;
434
435     if (!write_buffer (buf, d_period_size, sizeof_frame))  
436       return -1;        // No fixing this problem.  Say we're done.
437   }
438
439   return n;
440 }
441
442 /*
443  * Work function that deals with float to S32 conversion and
444  * mono to stereo kludge.
445  */
446 int
447 audio_alsa_sink::work_s32_1x2 (int noutput_items,
448                                gr_vector_const_void_star &input_items,
449                                gr_vector_void_star &output_items)
450 {
451   typedef gr_int32      sample_t;       // the type of samples we're creating
452   static const int NBITS = 32;          // # of bits in a sample
453   
454   assert (input_items.size () == 1);
455   static unsigned int nchan = 2;
456   const float **in = (const float **) &input_items[0];
457   sample_t *buf = (sample_t *) d_buffer;
458   int bi;
459   int n;
460
461   unsigned int sizeof_frame = nchan * sizeof (sample_t);
462   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
463
464   for (n = 0; n < noutput_items; n += d_period_size){
465
466     // process one period of data
467     bi = 0;
468     for (unsigned int i = 0; i < d_period_size; i++){
469       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
470       buf[bi++] = t;
471       buf[bi++] = t;
472     }
473
474     // update src pointers
475     in[0] += d_period_size;
476
477     if (!write_buffer (buf, d_period_size, sizeof_frame))  
478       return -1;        // No fixing this problem.  Say we're done.
479   }
480
481   return n;
482 }
483
484 bool
485 audio_alsa_sink::write_buffer (const void *vbuffer,
486                                unsigned nframes, unsigned sizeof_frame)
487 {
488   const unsigned char *buffer = (const unsigned char *) vbuffer;
489
490   while (nframes > 0){
491     int r = snd_pcm_writei (d_pcm_handle, buffer, nframes);
492     if (r == -EAGAIN)
493     {
494       if (d_ok_to_block == true)
495         continue;               // try again
496       
497       break;
498     }
499
500     else if (r == -EPIPE){      // underrun
501       d_nunderuns++;
502       fputs ("aU", stderr);
503       if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){
504         output_error_msg ("snd_pcm_prepare failed. Can't recover from underrun", r);
505         return false;
506       }
507       continue;                 // try again
508     }
509
510     else if (r == -ESTRPIPE){   // h/w is suspended (whatever that means)
511                                 // This is apparently related to power management
512       d_nsuspends++;
513       if ((r = snd_pcm_resume (d_pcm_handle)) < 0){
514         output_error_msg ("failed to resume from suspend", r);
515         return false;
516       }
517       continue;                 // try again
518     }
519
520     else if (r < 0){
521       output_error_msg ("snd_pcm_writei failed", r);
522       return false;
523     }
524
525     nframes -= r;
526     buffer += r * sizeof_frame;
527   }
528
529   return true;
530 }
531
532
533 void
534 audio_alsa_sink::output_error_msg (const char *msg, int err)
535 {
536   fprintf (stderr, "audio_alsa_sink[%s]: %s: %s\n",
537            snd_pcm_name (d_pcm_handle), msg,  snd_strerror (err));
538 }
539
540 void
541 audio_alsa_sink::bail (const char *msg, int err) throw (std::runtime_error)
542 {
543   output_error_msg (msg, err);
544   throw std::runtime_error ("audio_alsa_sink");
545 }