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