X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gr-audio-portaudio%2Fsrc%2Faudio_portaudio_source.cc;h=23801a8bf7e873602254797b1082c5683b5ff238;hb=ff6ce4dcf7c602cd94f840de21034634c95af806;hp=8b03ea8d817f821b949192dea3cf8168d0930949;hpb=86f5c92427b3f4bb30536d76cf63c3fca388fb2f;p=debian%2Fgnuradio diff --git a/gr-audio-portaudio/src/audio_portaudio_source.cc b/gr-audio-portaudio/src/audio_portaudio_source.cc index 8b03ea8d..23801a8b 100644 --- a/gr-audio-portaudio/src/audio_portaudio_source.cc +++ b/gr-audio-portaudio/src/audio_portaudio_source.cc @@ -1,12 +1,12 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) + * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in he hope that it will be useful, @@ -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,36 +83,32 @@ portaudio_source_callback (const void *inputBuffer, int nframes_room = self->d_writer->space_available() / nchan; if (nframes_to_copy <= nframes_room){ // We've got room for the data .. - if (LOGGING) - self->d_log->printf("PAsrc cb: f/b = %4ld\n", framesPerBuffer); + //if (LOGGING) + // self->d_log->printf("PAsrc cb: f/b = %4ld\n", framesPerBuffer); // copy from input buffer to ringbuffer - memcpy(self->d_writer->write_pointer(), - inputBuffer, - nframes_to_copy * nchan * sizeof(sample_t)); - self->d_writer->update_write_pointer(nframes_to_copy * nchan); + { + gruel::scoped_lock(d_ringbuffer_mutex); + + memcpy(self->d_writer->write_pointer(), + inputBuffer, + nframes_to_copy * nchan * sizeof(sample_t)); + self->d_writer->update_write_pointer(nframes_to_copy * nchan); - // Tell the source thread there is new data in the ringbuffer. - self->d_ringbuffer_ready.post(); + // Tell the source thread there is new data in the ringbuffer. + self->d_ringbuffer_ready = true; + } + + self->d_ringbuffer_cond.notify_one(); return paContinue; } else { // overrun - if (LOGGING) - self->d_log->printf("PAsrc cb: f/b = %4ld OVERRUN\n", framesPerBuffer); - self->d_noverruns++; ::write(2, "aO", 2); // FIXME change to non-blocking call -#if 0 - // copy any frames that will fit - memcpy(self->d_writer->write_pointer(), - inputBuffer, - nframes_room * nchan * sizeof(sample_t)); - self->d_writer->update_write_pointer(nframes_room * nchan); -#endif - - self->d_ringbuffer_ready.post(); // Tell the sink to get going! + self->d_ringbuffer_ready = false; + self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going! return paContinue; } } @@ -123,7 +119,7 @@ portaudio_source_callback (const void *inputBuffer, audio_portaudio_source_sptr audio_portaudio_make_source (int sampling_rate, const std::string dev, bool ok_to_block) { - return audio_portaudio_source_sptr (new audio_portaudio_source (sampling_rate, + return gnuradio::get_initial_sptr(new audio_portaudio_source (sampling_rate, dev, ok_to_block)); } @@ -139,12 +135,14 @@ audio_portaudio_source::audio_portaudio_source(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_noverruns(0) { memset(&d_input_parameters, 0, sizeof(d_input_parameters)); - if (LOGGING) - d_log = gri_logger::singleton(); + //if (LOGGING) + // d_log = gri_logger::singleton(); PaError err; int i, numDevices; @@ -302,11 +300,13 @@ audio_portaudio_source::work (int noutput_items, if (k > 0) // If we've produced anything so far, return that return k; - if (d_ok_to_block){ - d_ringbuffer_ready.wait(); // block here, then try again + if (d_ok_to_block) { + gruel:: scoped_lock guard(d_ringbuffer_mutex); + while (d_ringbuffer_ready == false) + d_ringbuffer_cond.wait(guard); // block here, then try again continue; } - + assert(k == 0); // There's no data and we're not allowed to block. @@ -319,27 +319,38 @@ audio_portaudio_source::work (int noutput_items, // FIXME We'll fill with zeros for now. Yes, it will "click"... // Fill with some frames of zeros - int nf = std::min(noutput_items - k, (int) d_portaudio_buffer_size_frames); - for (int i = 0; i < nf; i++){ - for (unsigned int c = 0; c < nchan; c++){ - out[c][k + i] = 0; + { + gruel::scoped_lock guard(d_ringbuffer_mutex); + + int nf = std::min(noutput_items - k, (int) d_portaudio_buffer_size_frames); + for (int i = 0; i < nf; i++){ + for (unsigned int c = 0; c < nchan; c++){ + out[c][k + i] = 0; + } } + k += nf; + + d_ringbuffer_ready = false; + return k; } - k += nf; - return k; } // We can read the smaller of the request and what's in the buffer. - int nf = std::min(noutput_items - k, nframes); + { + gruel::scoped_lock guard(d_ringbuffer_mutex); - const float *p = (const float *) d_reader->read_pointer(); - for (int i = 0; i < nf; i++){ - for (unsigned int c = 0; c < nchan; c++){ - out[c][k + i] = *p++; + int nf = std::min(noutput_items - k, nframes); + + const float *p = (const float *) d_reader->read_pointer(); + for (int i = 0; i < nf; i++){ + for (unsigned int c = 0; c < nchan; c++){ + out[c][k + i] = *p++; + } } + d_reader->update_read_pointer(nf * nchan); + k += nf; + d_ringbuffer_ready = false; } - d_reader->update_read_pointer(nf * nchan); - k += nf; } return k; // tell how many we actually did