Adding a "change in progress" check to alsa sink.
authorTom Rondeau <trondeau@vt.edu>
Tue, 7 Dec 2010 01:22:22 +0000 (20:22 -0500)
committerTom Rondeau <trondeau@vt.edu>
Tue, 7 Dec 2010 01:22:22 +0000 (20:22 -0500)
gr-audio-alsa/src/audio_alsa_sink.cc
gr-audio-alsa/src/audio_alsa_sink.h

index c28e23fea64bfaa06e6800c752d1905e38963a9e..84bf49151af4d8f1a9ceb3ded9c6b64c8d544e35 100644 (file)
@@ -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)
index f3007f60f8a0503040873966c613776feea07d45..811cc6c8cbf86f55b5fb87c83c0db6e1b357e6b9 100644 (file)
@@ -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);