A new patch for fixing the alsa restart issue. Submitted by Volker Schroer.
[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   // Check the state of the stream
225   // Ensure that the pcm is in a state where we can still mess with the hw_params
226   snd_pcm_state_t state;
227   state=snd_pcm_state(d_pcm_handle);
228   if ( state== SND_PCM_STATE_RUNNING)
229     return true;  // If stream is running, don't change any parameters
230   else if(state == SND_PCM_STATE_XRUN )
231     snd_pcm_prepare ( d_pcm_handle ); // Prepare stream on underrun, and we can set parameters;
232   
233   bool special_case = nchan == 1 && d_special_case_mono_to_stereo;
234   if (special_case)
235     nchan = 2;
236   
237   err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, nchan);
238
239   if (err < 0){
240     output_error_msg ("set_channels failed", err);
241     return false;
242   }
243
244   // set the parameters into the driver...
245   err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
246   if (err < 0){
247     output_error_msg ("snd_pcm_hw_params failed", err);
248     return false;
249   }
250
251   // get current s/w params
252   err = snd_pcm_sw_params_current (d_pcm_handle, d_sw_params);
253   if (err < 0)
254     bail ("snd_pcm_sw_params_current", err);
255   
256   // Tell the PCM device to wait to start until we've filled
257   // it's buffers half way full.  This helps avoid audio underruns.
258
259   err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle,
260                                               d_sw_params,
261                                               d_nperiods * d_period_size / 2);
262   if (err < 0)
263     bail ("snd_pcm_sw_params_set_start_threshold", err);
264
265   // store the s/w params
266   err = snd_pcm_sw_params (d_pcm_handle, d_sw_params);
267   if (err < 0)
268     bail ("snd_pcm_sw_params", err);
269
270   d_buffer_size_bytes =
271     d_period_size * nchan * snd_pcm_format_size (d_format, 1);
272
273   d_buffer = new char [d_buffer_size_bytes];
274
275   if (CHATTY_DEBUG)
276     fprintf (stdout, "audio_alsa_sink[%s]: sample resolution = %d bits\n",
277              snd_pcm_name (d_pcm_handle),
278              snd_pcm_hw_params_get_sbits (d_hw_params));
279
280   switch (d_format){
281   case SND_PCM_FORMAT_S16:
282     if (special_case)
283       d_worker = &audio_alsa_sink::work_s16_1x2;
284     else
285       d_worker = &audio_alsa_sink::work_s16;
286     break;
287
288   case SND_PCM_FORMAT_S32:
289     if (special_case)
290       d_worker = &audio_alsa_sink::work_s32_1x2;
291     else
292       d_worker = &audio_alsa_sink::work_s32;
293     break;
294
295   default:
296     assert (0);
297   }
298   return true;
299 }
300
301 audio_alsa_sink::~audio_alsa_sink ()
302 {
303   if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING)
304     snd_pcm_drop (d_pcm_handle);
305
306   snd_pcm_close(d_pcm_handle);
307   delete [] ((char *) d_hw_params);
308   delete [] ((char *) d_sw_params);
309   delete [] d_buffer;
310 }
311
312 int
313 audio_alsa_sink::work (int noutput_items,
314                        gr_vector_const_void_star &input_items,
315                        gr_vector_void_star &output_items)
316 {
317   assert ((noutput_items % d_period_size) == 0);
318
319   // this is a call through a pointer to a method...
320   return (this->*d_worker)(noutput_items, input_items, output_items);
321 }
322
323 /*
324  * Work function that deals with float to S16 conversion
325  */
326 int
327 audio_alsa_sink::work_s16 (int noutput_items,
328                            gr_vector_const_void_star &input_items,
329                            gr_vector_void_star &output_items)
330 {
331   typedef gr_int16      sample_t;       // the type of samples we're creating
332   static const int NBITS = 16;          // # of bits in a sample
333   
334   unsigned int nchan = input_items.size ();
335   const float **in = (const float **) &input_items[0];
336   sample_t *buf = (sample_t *) d_buffer;
337   int bi;
338   int n;
339
340   unsigned int sizeof_frame = nchan * sizeof (sample_t);
341   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
342
343   for (n = 0; n < noutput_items; n += d_period_size){
344
345     // process one period of data
346     bi = 0;
347     for (unsigned int i = 0; i < d_period_size; i++){
348       for (unsigned int chan = 0; chan < nchan; chan++){
349         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
350       }
351     }
352
353     // update src pointers
354     for (unsigned int chan = 0; chan < nchan; chan++)
355       in[chan] += d_period_size;
356
357     if (!write_buffer (buf, d_period_size, sizeof_frame))  
358       return -1;        // No fixing this problem.  Say we're done.
359   }
360
361   return n;
362 }
363
364
365 /*
366  * Work function that deals with float to S32 conversion
367  */
368 int
369 audio_alsa_sink::work_s32 (int noutput_items,
370                            gr_vector_const_void_star &input_items,
371                            gr_vector_void_star &output_items)
372 {
373   typedef gr_int32      sample_t;       // the type of samples we're creating
374   static const int NBITS = 32;          // # of bits in a sample
375   
376   unsigned int nchan = input_items.size ();
377   const float **in = (const float **) &input_items[0];
378   sample_t *buf = (sample_t *) d_buffer;
379   int bi;
380   int n;
381
382   unsigned int sizeof_frame = nchan * sizeof (sample_t);
383   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
384
385   for (n = 0; n < noutput_items; n += d_period_size){
386
387     // process one period of data
388     bi = 0;
389     for (unsigned int i = 0; i < d_period_size; i++){
390       for (unsigned int chan = 0; chan < nchan; chan++){
391         buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1));
392       }
393     }
394
395     // update src pointers
396     for (unsigned int chan = 0; chan < nchan; chan++)
397       in[chan] += d_period_size;
398
399     if (!write_buffer (buf, d_period_size, sizeof_frame))  
400       return -1;        // No fixing this problem.  Say we're done.
401   }
402
403   return n;
404 }
405
406 /*
407  * Work function that deals with float to S16 conversion and
408  * mono to stereo kludge.
409  */
410 int
411 audio_alsa_sink::work_s16_1x2 (int noutput_items,
412                                gr_vector_const_void_star &input_items,
413                                gr_vector_void_star &output_items)
414 {
415   typedef gr_int16      sample_t;       // the type of samples we're creating
416   static const int NBITS = 16;          // # of bits in a sample
417   
418   assert (input_items.size () == 1);
419   static const unsigned int nchan = 2;
420   const float **in = (const float **) &input_items[0];
421   sample_t *buf = (sample_t *) d_buffer;
422   int bi;
423   int n;
424
425   unsigned int sizeof_frame = nchan * sizeof (sample_t);
426   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
427
428   for (n = 0; n < noutput_items; n += d_period_size){
429
430     // process one period of data
431     bi = 0;
432     for (unsigned int i = 0; i < d_period_size; i++){
433       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
434       buf[bi++] = t;
435       buf[bi++] = t;
436     }
437
438     // update src pointers
439     in[0] += d_period_size;
440
441     if (!write_buffer (buf, d_period_size, sizeof_frame))  
442       return -1;        // No fixing this problem.  Say we're done.
443   }
444
445   return n;
446 }
447
448 /*
449  * Work function that deals with float to S32 conversion and
450  * mono to stereo kludge.
451  */
452 int
453 audio_alsa_sink::work_s32_1x2 (int noutput_items,
454                                gr_vector_const_void_star &input_items,
455                                gr_vector_void_star &output_items)
456 {
457   typedef gr_int32      sample_t;       // the type of samples we're creating
458   static const int NBITS = 32;          // # of bits in a sample
459   
460   assert (input_items.size () == 1);
461   static unsigned int nchan = 2;
462   const float **in = (const float **) &input_items[0];
463   sample_t *buf = (sample_t *) d_buffer;
464   int bi;
465   int n;
466
467   unsigned int sizeof_frame = nchan * sizeof (sample_t);
468   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
469
470   for (n = 0; n < noutput_items; n += d_period_size){
471
472     // process one period of data
473     bi = 0;
474     for (unsigned int i = 0; i < d_period_size; i++){
475       sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1));
476       buf[bi++] = t;
477       buf[bi++] = t;
478     }
479
480     // update src pointers
481     in[0] += d_period_size;
482
483     if (!write_buffer (buf, d_period_size, sizeof_frame))  
484       return -1;        // No fixing this problem.  Say we're done.
485   }
486
487   return n;
488 }
489
490 bool
491 audio_alsa_sink::write_buffer (const void *vbuffer,
492                                unsigned nframes, unsigned sizeof_frame)
493 {
494   const unsigned char *buffer = (const unsigned char *) vbuffer;
495
496   while (nframes > 0){
497     int r = snd_pcm_writei (d_pcm_handle, buffer, nframes);
498     if (r == -EAGAIN)
499     {
500       if (d_ok_to_block == true)
501         continue;               // try again
502       
503       break;
504     }
505
506     else if (r == -EPIPE){      // underrun
507       d_nunderuns++;
508       fputs ("aU", stderr);
509       if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){
510         output_error_msg ("snd_pcm_prepare failed. Can't recover from underrun", r);
511         return false;
512       }
513       continue;                 // try again
514     }
515
516     else if (r == -ESTRPIPE){   // h/w is suspended (whatever that means)
517                                 // This is apparently related to power management
518       d_nsuspends++;
519       if ((r = snd_pcm_resume (d_pcm_handle)) < 0){
520         output_error_msg ("failed to resume from suspend", r);
521         return false;
522       }
523       continue;                 // try again
524     }
525
526     else if (r < 0){
527       output_error_msg ("snd_pcm_writei failed", r);
528       return false;
529     }
530
531     nframes -= r;
532     buffer += r * sizeof_frame;
533   }
534
535   return true;
536 }
537
538
539 void
540 audio_alsa_sink::output_error_msg (const char *msg, int err)
541 {
542   fprintf (stderr, "audio_alsa_sink[%s]: %s: %s\n",
543            snd_pcm_name (d_pcm_handle), msg,  snd_strerror (err));
544 }
545
546 void
547 audio_alsa_sink::bail (const char *msg, int err) throw (std::runtime_error)
548 {
549   output_error_msg (msg, err);
550   throw std::runtime_error ("audio_alsa_sink");
551 }