From c7c0b86afa255983db3def0a15e1201455ade460 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 30 Oct 2010 16:29:27 -0400 Subject: Added a check in alsa sink if error has occurred due to blocking; if so, it will just drop samples and not get backed up. Patch taken from Marcus Leech 10/29/2010. --- gr-audio-alsa/src/audio_alsa_sink.cc | 12 +++++++++--- gr-audio-alsa/src/audio_alsa_sink.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/gr-audio-alsa/src/audio_alsa_sink.cc b/gr-audio-alsa/src/audio_alsa_sink.cc index d6b7f84cf..c28e23fea 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.cc +++ b/gr-audio-alsa/src/audio_alsa_sink.cc @@ -90,7 +90,7 @@ audio_alsa_sink::audio_alsa_sink (int sampling_rate, d_period_size (0), d_buffer_size_bytes (0), d_buffer (0), d_worker (0), d_special_case_mono_to_stereo (false), - d_nunderuns (0), d_nsuspends (0) + d_nunderuns (0), d_nsuspends (0), d_ok_to_block(ok_to_block) { CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false); @@ -100,6 +100,8 @@ audio_alsa_sink::audio_alsa_sink (int sampling_rate, // open the device for playback error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (), SND_PCM_STREAM_PLAYBACK, 0); + if (ok_to_block == false) + snd_pcm_nonblock(d_pcm_handle, !ok_to_block); if (error < 0){ fprintf (stderr, "audio_alsa_sink[%s]: %s\n", d_device_name.c_str(), snd_strerror(error)); @@ -287,7 +289,6 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) default: assert (0); } - return true; } @@ -489,7 +490,12 @@ audio_alsa_sink::write_buffer (const void *vbuffer, while (nframes > 0){ int r = snd_pcm_writei (d_pcm_handle, buffer, nframes); if (r == -EAGAIN) - continue; // try again + { + if (d_ok_to_block == true) + continue; // try again + + break; + } else if (r == -EPIPE){ // underrun d_nunderuns++; diff --git a/gr-audio-alsa/src/audio_alsa_sink.h b/gr-audio-alsa/src/audio_alsa_sink.h index d4b540382..f3007f60f 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.h +++ b/gr-audio-alsa/src/audio_alsa_sink.h @@ -83,6 +83,7 @@ class audio_alsa_sink : public gr_sync_block { // random stats int d_nunderuns; // count of underruns int d_nsuspends; // count of suspends + bool d_ok_to_block; // defaults to "true", controls blocking/non-block I/O void output_error_msg (const char *msg, int err); void bail (const char *msg, int err) throw (std::runtime_error); -- cgit From ed4abf6f759a421bc845d9138f82df84bb4bbf96 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 6 Dec 2010 20:22:22 -0500 Subject: Adding a "change in progress" check to alsa sink. --- gr-audio-alsa/src/audio_alsa_sink.cc | 18 +++++++++++++++++- gr-audio-alsa/src/audio_alsa_sink.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/gr-audio-alsa/src/audio_alsa_sink.cc b/gr-audio-alsa/src/audio_alsa_sink.cc index c28e23fea..84bf49151 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.cc +++ b/gr-audio-alsa/src/audio_alsa_sink.cc @@ -90,7 +90,8 @@ audio_alsa_sink::audio_alsa_sink (int sampling_rate, d_period_size (0), d_buffer_size_bytes (0), d_buffer (0), d_worker (0), d_special_case_mono_to_stereo (false), - d_nunderuns (0), d_nsuspends (0), d_ok_to_block(ok_to_block) + d_nunderuns (0), d_nsuspends (0), d_ok_to_block(ok_to_block), + d_change_in_progress(false) { CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false); @@ -224,6 +225,11 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) // FIXME check_topology may be called more than once. // Ensure that the pcm is in a state where we can still mess with the hw_params + d_change_in_progress = true; + + if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING) + snd_pcm_drop (d_pcm_handle); + bool special_case = nchan == 1 && d_special_case_mono_to_stereo; if (special_case) nchan = 2; @@ -232,6 +238,7 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) if (err < 0){ output_error_msg ("set_channels failed", err); + d_change_in_progress = false; return false; } @@ -239,6 +246,7 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) err = snd_pcm_hw_params(d_pcm_handle, d_hw_params); if (err < 0){ output_error_msg ("snd_pcm_hw_params failed", err); + d_change_in_progress = false; return false; } @@ -289,6 +297,7 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) default: assert (0); } + d_change_in_progress = false; return true; } @@ -487,6 +496,13 @@ audio_alsa_sink::write_buffer (const void *vbuffer, { const unsigned char *buffer = (const unsigned char *) vbuffer; + int change_counter = 10; + while (d_change_in_progress == true && change_counter >= 0) { + change_counter--; + usleep(10000); + } + d_change_in_progress = false; + while (nframes > 0){ int r = snd_pcm_writei (d_pcm_handle, buffer, nframes); if (r == -EAGAIN) diff --git a/gr-audio-alsa/src/audio_alsa_sink.h b/gr-audio-alsa/src/audio_alsa_sink.h index f3007f60f..811cc6c8c 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.h +++ b/gr-audio-alsa/src/audio_alsa_sink.h @@ -83,6 +83,7 @@ class audio_alsa_sink : public gr_sync_block { // random stats int d_nunderuns; // count of underruns int d_nsuspends; // count of suspends + bool d_change_in_progress; // Topology change in progress--used as spinlock for write_buffer bool d_ok_to_block; // defaults to "true", controls blocking/non-block I/O void output_error_msg (const char *msg, int err); -- cgit From a8e58dba4d820e0b66d89bf05af29c381e46eef9 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 22 Dec 2010 17:11:44 -0500 Subject: Reverting last change in alsa. --- gr-audio-alsa/src/audio_alsa_sink.cc | 18 +----------------- gr-audio-alsa/src/audio_alsa_sink.h | 1 - 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/gr-audio-alsa/src/audio_alsa_sink.cc b/gr-audio-alsa/src/audio_alsa_sink.cc index 84bf49151..c28e23fea 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.cc +++ b/gr-audio-alsa/src/audio_alsa_sink.cc @@ -90,8 +90,7 @@ audio_alsa_sink::audio_alsa_sink (int sampling_rate, d_period_size (0), d_buffer_size_bytes (0), d_buffer (0), d_worker (0), d_special_case_mono_to_stereo (false), - d_nunderuns (0), d_nsuspends (0), d_ok_to_block(ok_to_block), - d_change_in_progress(false) + d_nunderuns (0), d_nsuspends (0), d_ok_to_block(ok_to_block) { CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false); @@ -225,11 +224,6 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) // FIXME check_topology may be called more than once. // Ensure that the pcm is in a state where we can still mess with the hw_params - d_change_in_progress = true; - - if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING) - snd_pcm_drop (d_pcm_handle); - bool special_case = nchan == 1 && d_special_case_mono_to_stereo; if (special_case) nchan = 2; @@ -238,7 +232,6 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) if (err < 0){ output_error_msg ("set_channels failed", err); - d_change_in_progress = false; return false; } @@ -246,7 +239,6 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) err = snd_pcm_hw_params(d_pcm_handle, d_hw_params); if (err < 0){ output_error_msg ("snd_pcm_hw_params failed", err); - d_change_in_progress = false; return false; } @@ -297,7 +289,6 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) default: assert (0); } - d_change_in_progress = false; return true; } @@ -496,13 +487,6 @@ audio_alsa_sink::write_buffer (const void *vbuffer, { const unsigned char *buffer = (const unsigned char *) vbuffer; - int change_counter = 10; - while (d_change_in_progress == true && change_counter >= 0) { - change_counter--; - usleep(10000); - } - d_change_in_progress = false; - while (nframes > 0){ int r = snd_pcm_writei (d_pcm_handle, buffer, nframes); if (r == -EAGAIN) diff --git a/gr-audio-alsa/src/audio_alsa_sink.h b/gr-audio-alsa/src/audio_alsa_sink.h index 811cc6c8c..f3007f60f 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.h +++ b/gr-audio-alsa/src/audio_alsa_sink.h @@ -83,7 +83,6 @@ class audio_alsa_sink : public gr_sync_block { // random stats int d_nunderuns; // count of underruns int d_nsuspends; // count of suspends - bool d_change_in_progress; // Topology change in progress--used as spinlock for write_buffer bool d_ok_to_block; // defaults to "true", controls blocking/non-block I/O void output_error_msg (const char *msg, int err); -- cgit From 64ee9a2973e6c217c54f8cb0433ab24b0e52e2cc Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 22 Dec 2010 17:41:30 -0500 Subject: A new patch for fixing the alsa restart issue. Submitted by Volker Schroer. --- gr-audio-alsa/src/audio_alsa_sink.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gr-audio-alsa/src/audio_alsa_sink.cc b/gr-audio-alsa/src/audio_alsa_sink.cc index c28e23fea..d44a93b3f 100644 --- a/gr-audio-alsa/src/audio_alsa_sink.cc +++ b/gr-audio-alsa/src/audio_alsa_sink.cc @@ -221,9 +221,15 @@ audio_alsa_sink::check_topology (int ninputs, int noutputs) int nchan = ninputs; int err; - // FIXME check_topology may be called more than once. + // Check the state of the stream // Ensure that the pcm is in a state where we can still mess with the hw_params - + snd_pcm_state_t state; + state=snd_pcm_state(d_pcm_handle); + if ( state== SND_PCM_STATE_RUNNING) + return true; // If stream is running, don't change any parameters + else if(state == SND_PCM_STATE_XRUN ) + snd_pcm_prepare ( d_pcm_handle ); // Prepare stream on underrun, and we can set parameters; + bool special_case = nchan == 1 && d_special_case_mono_to_stereo; if (special_case) nchan = 2; -- cgit