X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gr-audio-portaudio%2Fsrc%2Faudio_portaudio_sink.cc;h=64e64ccf4536a3fdcb8b649ba0557234b41dd9e9;hb=e5198a304a12410da8936a16900feba2fad1edae;hp=13197192f25c1ea8113a416d4c070afbc1026bc9;hpb=937b719d2e57d0497293d603da10cac2532346f6;p=debian%2Fgnuradio diff --git a/gr-audio-portaudio/src/audio_portaudio_sink.cc b/gr-audio-portaudio/src/audio_portaudio_sink.cc index 13197192..64e64ccf 100644 --- a/gr-audio-portaudio/src/audio_portaudio_sink.cc +++ b/gr-audio-portaudio/src/audio_portaudio_sink.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -32,9 +32,9 @@ #include #include #include -#include +#include -#define LOGGING 0 // define to 0 or 1 +//#define LOGGING 0 // define to 0 or 1 #define SAMPLE_FORMAT paFloat32 typedef float sample_t; @@ -83,31 +83,36 @@ portaudio_sink_callback (const void *inputBuffer, int navail_samples = self->d_reader->items_available(); - if (nreqd_samples <= navail_samples){ // We've got enough data... - if (LOGGING) - self->d_log->printf("PAsink cb: f/b = %4ld\n", framesPerBuffer); - // copy from ringbuffer into output buffer - memcpy(outputBuffer, - self->d_reader->read_pointer(), - nreqd_samples * sizeof(sample_t)); - self->d_reader->update_read_pointer(nreqd_samples); - + if (nreqd_samples <= navail_samples) { // We've got enough data... + { + gruel::scoped_lock guard(self->d_ringbuffer_mutex); + + memcpy(outputBuffer, + self->d_reader->read_pointer(), + nreqd_samples * sizeof(sample_t)); + self->d_reader->update_read_pointer(nreqd_samples); + + self->d_ringbuffer_ready = true; + } + // Tell the sink thread there is new room in the ringbuffer. - self->d_ringbuffer_ready.post(); + self->d_ringbuffer_cond.notify_one(); return paContinue; } else { // underrun - if (LOGGING) - self->d_log->printf("PAsink cb: f/b = %4ld UNDERRUN\n", framesPerBuffer); - self->d_nunderuns++; - ::write(2, "aU", 2); // FIXME change to non-blocking call + ssize_t r = ::write(2, "aU", 2); // FIXME change to non-blocking call + if(r == -1) { + perror("audio_portaudio_source::portaudio_source_callback write error to stderr."); + } // FIXME we should transfer what we've got and pad the rest memset(outputBuffer, 0, nreqd_samples * sizeof(sample_t)); - self->d_ringbuffer_ready.post(); // Tell the sink to get going! + self->d_ringbuffer_ready = true; + self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going! + return paContinue; } } @@ -118,7 +123,7 @@ portaudio_sink_callback (const void *inputBuffer, audio_portaudio_sink_sptr audio_portaudio_make_sink (int sampling_rate, const std::string dev, bool ok_to_block) { - return audio_portaudio_sink_sptr (new audio_portaudio_sink (sampling_rate, + return gnuradio::get_initial_sptr(new audio_portaudio_sink (sampling_rate, dev, ok_to_block)); } @@ -134,12 +139,14 @@ audio_portaudio_sink::audio_portaudio_sink(int sampling_rate, d_verbose(gr_prefs::singleton()->get_bool("audio_portaudio", "verbose", false)), d_portaudio_buffer_size_frames(0), d_stream(0), - d_ringbuffer_ready(1, 1), // binary semaphore + d_ringbuffer_mutex(), + d_ringbuffer_cond(), + d_ringbuffer_ready(false), d_nunderuns(0) { memset(&d_output_parameters, 0, sizeof(d_output_parameters)); - if (LOGGING) - d_log = gri_logger::singleton(); + //if (LOGGING) + // d_log = gri_logger::singleton(); PaError err; int i, numDevices; @@ -296,12 +303,17 @@ audio_portaudio_sink::work (int noutput_items, const unsigned nchan = d_output_parameters.channelCount; // # of channels == samples/frame int k; - for (k = 0; k < noutput_items; ){ + for (k = 0; k < noutput_items; ){ int nframes = d_writer->space_available() / nchan; // How much space in ringbuffer if (nframes == 0){ // no room... if (d_ok_to_block){ - d_ringbuffer_ready.wait(); // block here, then try again + { + gruel::scoped_lock guard(d_ringbuffer_mutex); + while (!d_ringbuffer_ready) + d_ringbuffer_cond.wait(guard); + } + continue; } else { @@ -315,16 +327,21 @@ audio_portaudio_sink::work (int noutput_items, } // We can write the smaller of the request and the room we've got - int nf = std::min(noutput_items - k, nframes); - - float *p = (float *) d_writer->write_pointer(); - for (int i = 0; i < nf; i++){ - for (unsigned int c = 0; c < nchan; c++){ - *p++ = in[c][k + i]; - } + { + gruel::scoped_lock guard(d_ringbuffer_mutex); + + int nf = std::min(noutput_items - k, nframes); + float *p = (float *) d_writer->write_pointer(); + + for (int i = 0; i < nf; i++) + for (unsigned int c = 0; c < nchan; c++) + *p++ = in[c][k + i]; + + d_writer->update_write_pointer(nf * nchan); + k += nf; + + d_ringbuffer_ready = false; } - d_writer->update_write_pointer(nf * nchan); - k += nf; } return k; // tell how many we actually did