/* -*- c++ -*- */
/*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
const std::string dev,
bool ok_to_block)
{
- return audio_alsa_sink_sptr (new audio_alsa_sink (sampling_rate, dev,
+ return gnuradio::get_initial_sptr(new audio_alsa_sink (sampling_rate, dev,
ok_to_block));
}
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),
+ d_change_in_progress(false)
{
CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false);
// 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));
// Specify the access methods we implement
// For now, we only handle RW_INTERLEAVED...
snd_pcm_access_mask_t *access_mask;
- snd_pcm_access_mask_alloca (&access_mask);
+ snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
+ snd_pcm_access_mask_alloca (access_mask_ptr);
snd_pcm_access_mask_none (access_mask);
snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
// snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
// 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;
if (err < 0){
output_error_msg ("set_channels failed", err);
+ d_change_in_progress = false;
return false;
}
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;
}
default:
assert (0);
}
-
+ d_change_in_progress = false;
return true;
}
{
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)
- continue; // try again
+ {
+ if (d_ok_to_block == true)
+ continue; // try again
+
+ break;
+ }
else if (r == -EPIPE){ // underrun
d_nunderuns++;