diff options
-rw-r--r-- | config/grc_gr_audio_portaudio.m4 | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/Makefile.am | 2 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gri_logger.cc | 178 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gri_logger.h | 59 | ||||
-rw-r--r-- | gr-audio-portaudio/src/Makefile.am | 1 | ||||
-rw-r--r-- | gr-audio-portaudio/src/audio_portaudio_sink.cc | 67 | ||||
-rw-r--r-- | gr-audio-portaudio/src/audio_portaudio_sink.h | 6 | ||||
-rw-r--r-- | gr-audio-portaudio/src/audio_portaudio_source.cc | 82 | ||||
-rw-r--r-- | gr-audio-portaudio/src/audio_portaudio_source.h | 13 |
9 files changed, 97 insertions, 312 deletions
diff --git a/config/grc_gr_audio_portaudio.m4 b/config/grc_gr_audio_portaudio.m4 index 08d71f8fb..ff551b38a 100644 --- a/config/grc_gr_audio_portaudio.m4 +++ b/config/grc_gr_audio_portaudio.m4 @@ -22,7 +22,6 @@ AC_DEFUN([GRC_GR_AUDIO_PORTAUDIO],[ dnl Don't do gr-audio-portaudio if gnuradio-core skipped GRC_CHECK_DEPENDENCY(gr-audio-portaudio, gnuradio-core) - GRC_CHECK_DEPENDENCY(gr-audio-portaudio, omnithread) dnl If execution gets to here, $passed will be: dnl with : if the --with code didn't error out diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am index 9eacd137d..c52554645 100644 --- a/gnuradio-core/src/lib/io/Makefile.am +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -39,7 +39,6 @@ libio_la_SOURCES = \ gr_oscope_guts.cc \ gr_oscope_sink_f.cc \ gr_oscope_sink_x.cc \ - gri_logger.cc \ i2c.cc \ i2c_bitbang.cc \ i2c_bbio.cc \ @@ -72,7 +71,6 @@ grinclude_HEADERS = \ gr_oscope_sink_f.h \ gr_oscope_sink_x.h \ gr_trigger_mode.h \ - gri_logger.h \ i2c.h \ i2c_bitbang.h \ i2c_bbio.h \ diff --git a/gnuradio-core/src/lib/io/gri_logger.cc b/gnuradio-core/src/lib/io/gri_logger.cc deleted file mode 100644 index 473a7c5ed..000000000 --- a/gnuradio-core/src/lib/io/gri_logger.cc +++ /dev/null @@ -1,178 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009 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 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if 0 // This needs reimplementation with boost threads and synchronization - -#include <gri_logger.h> -#include <stdio.h> -#include <stdarg.h> -#include <stdexcept> -#include <boost/weak_ptr.hpp> -#include <string.h> - - -/* - * This class creates the thread that reads from the ringbuffer and - * and writes to the file. This is opaque to the user. - */ -class gri_log_poster : public omni_thread -{ - FILE *d_fp; - gr_buffer_sptr d_writer; - gr_buffer_reader_sptr d_reader; - omni_semaphore d_ringbuffer_ready; - volatile bool d_time_to_die; - volatile bool d_writer_overrun; - - virtual void* run_undetached(void * arg); - -public: - gri_log_poster(const char *filename); - ~gri_log_poster(); - - void kill() { d_time_to_die = true; post(); } - gr_buffer_sptr writer() const { return d_writer; } - void post() { d_ringbuffer_ready.post(); } - void note_writer_overrun() { d_writer_overrun = true; } -}; - -gri_log_poster::gri_log_poster(const char *filename) - : omni_thread(), - d_ringbuffer_ready(1, 1), // binary semaphore - d_time_to_die(false), - d_writer_overrun(false) -{ - if ((d_fp = fopen(filename, "w")) == 0){ - perror (filename); - throw std::runtime_error("can't open file"); - } - - // Create a 1MB buffer. - d_writer = gr_make_buffer(1 * 1024 * 1024, sizeof(unsigned char)); - d_reader = gr_buffer_add_reader(d_writer, 0); - - start_undetached(); // start the thread -} - -gri_log_poster::~gri_log_poster() -{ - if (d_fp != 0){ - fclose(d_fp); - d_fp = 0; - } -} - -/* - * This is the body of the logging thread. - */ -void * -gri_log_poster::run_undetached(void *arg) -{ - int nbytes; - - //fprintf(stderr, "Enter: run_undetached!\n"); - - while (!d_time_to_die){ - while ((nbytes = d_reader->items_available()) > 0){ - fwrite(d_reader->read_pointer(), 1, nbytes, d_fp); - d_reader->update_read_pointer(nbytes); - } - fflush(d_fp); - d_ringbuffer_ready.wait(); - - if (d_writer_overrun){ - fputs(">>>>> gri_logger: writer overrun. Info lost <<<<<\n", d_fp); - d_writer_overrun = false; - } - } - - // fprintf(stderr, "Exit: run_undetached!\n"); - return 0; -} - -// ------------------------------------------------------------------------ - -static boost::weak_ptr<gri_logger> s_singleton; // weak pointer IQ test ;-) -static omni_mutex s_singleton_mutex; - -gri_logger_sptr -gri_logger::singleton() -{ - omni_mutex_lock l(s_singleton_mutex); - gri_logger_sptr r; - - if (r = s_singleton.lock()) - return r; - - r = gri_logger_sptr(new gri_logger("gri_logger.log")); - s_singleton = r; - return r; -} - - -gri_logger::gri_logger(const char *filename) -{ - d_poster = new gri_log_poster(filename); -} - -gri_logger::~gri_logger() -{ - d_poster->kill(); - d_poster->join(NULL); -} - -void -gri_logger::write(const void *buf, size_t count) -{ - omni_mutex_lock l(d_write_mutex); - gr_buffer_sptr writer = d_poster->writer(); - - // either write it all, or drop it on the ground - if (count <= (size_t) writer->space_available()){ - memcpy(writer->write_pointer(), buf, count); - writer->update_write_pointer(count); - d_poster->post(); - } - else { - d_poster->note_writer_overrun(); - } -} - -void -gri_logger::printf(const char *format, ...) -{ - va_list ap; - char buf[4096]; - int n; - - va_start(ap, format); - n = vsnprintf(buf, sizeof(buf), format, ap); - va_end(ap); - if (n > -1 && n < (ssize_t) sizeof(buf)) - write(buf, n); -} - -#endif diff --git a/gnuradio-core/src/lib/io/gri_logger.h b/gnuradio-core/src/lib/io/gri_logger.h deleted file mode 100644 index 0a1414540..000000000 --- a/gnuradio-core/src/lib/io/gri_logger.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009 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 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GRI_LOGGER_H -#define INCLUDED_GRI_LOGGER_H - -#if 0 // This needs reimplementation with boost threads and synchronization - -#include <stddef.h> -#include <gnuradio/omnithread.h> -#include <gr_buffer.h> - -class gri_log_poster; -class gri_logger; -typedef boost::shared_ptr<gri_logger> gri_logger_sptr; - - -/*! - * \brief non-blocking logging to a file. - * - * In reality, this may block, but only for a bounded time. - * Trust me, it's safe to use from portaudio and JACK callbacks. - */ -class gri_logger -{ - gri_log_poster *d_poster; - omni_mutex d_write_mutex; - -public: - static gri_logger_sptr singleton(); - - gri_logger(const char *filename); - ~gri_logger(); - - void write(const void *buf, size_t count); - void printf(const char *format, ...); -}; - -#endif - -#endif /* INCLUDED_GRI_LOGGER_H */ diff --git a/gr-audio-portaudio/src/Makefile.am b/gr-audio-portaudio/src/Makefile.am index 20213d16b..1df6bbcea 100644 --- a/gr-audio-portaudio/src/Makefile.am +++ b/gr-audio-portaudio/src/Makefile.am @@ -46,7 +46,6 @@ libgnuradio_audio_portaudio_la_SOURCES = \ libgnuradio_audio_portaudio_la_LIBADD = \ $(GNURADIO_CORE_LA) \ - $(OMNITHREAD_LA) \ $(PORTAUDIO_LIBS) libgnuradio_audio_portaudio_la_LDFLAGS = \ diff --git a/gr-audio-portaudio/src/audio_portaudio_sink.cc b/gr-audio-portaudio/src/audio_portaudio_sink.cc index 2e48feb4a..65a38f911 100644 --- a/gr-audio-portaudio/src/audio_portaudio_sink.cc +++ b/gr-audio-portaudio/src/audio_portaudio_sink.cc @@ -32,7 +32,6 @@ #include <unistd.h> #include <stdexcept> #include <gri_portaudio.h> -#include <gnuradio/omnithread.h> #include <string.h> //#define LOGGING 0 // define to 0 or 1 @@ -84,31 +83,33 @@ 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 // 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; } } @@ -135,7 +136,9 @@ 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)); @@ -297,12 +300,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 { @@ -316,16 +324,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 diff --git a/gr-audio-portaudio/src/audio_portaudio_sink.h b/gr-audio-portaudio/src/audio_portaudio_sink.h index 1a0729799..71cbfcf9f 100644 --- a/gr-audio-portaudio/src/audio_portaudio_sink.h +++ b/gr-audio-portaudio/src/audio_portaudio_sink.h @@ -24,7 +24,7 @@ #include <gr_sync_block.h> #include <gr_buffer.h> -#include <gnuradio/omnithread.h> +#include <gruel/thread.h> #include <string> #include <portaudio.h> #include <stdexcept> @@ -74,8 +74,10 @@ class audio_portaudio_sink : public gr_sync_block { gr_buffer_sptr d_writer; // buffer used between work and callback gr_buffer_reader_sptr d_reader; - omni_semaphore d_ringbuffer_ready; // binary semaphore + gruel::mutex d_ringbuffer_mutex; + gruel::condition_variable d_ringbuffer_cond; + bool d_ringbuffer_ready; // random stats int d_nunderuns; // count of underruns diff --git a/gr-audio-portaudio/src/audio_portaudio_source.cc b/gr-audio-portaudio/src/audio_portaudio_source.cc index 9e883ad8a..484b7f1e5 100644 --- a/gr-audio-portaudio/src/audio_portaudio_source.cc +++ b/gr-audio-portaudio/src/audio_portaudio_source.cc @@ -32,7 +32,6 @@ #include <unistd.h> #include <stdexcept> #include <gri_portaudio.h> -#include <gnuradio/omnithread.h> #include <string.h> //#define LOGGING 0 // define to 0 or 1 @@ -88,32 +87,28 @@ portaudio_source_callback (const void *inputBuffer, // 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; } } @@ -140,7 +135,9 @@ 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)); @@ -303,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. @@ -320,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 diff --git a/gr-audio-portaudio/src/audio_portaudio_source.h b/gr-audio-portaudio/src/audio_portaudio_source.h index 3102db739..31e70a127 100644 --- a/gr-audio-portaudio/src/audio_portaudio_source.h +++ b/gr-audio-portaudio/src/audio_portaudio_source.h @@ -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 * @@ -24,11 +24,10 @@ #include <gr_sync_block.h> #include <gr_buffer.h> -#include <gnuradio/omnithread.h> +#include <gruel/thread.h> #include <string> #include <portaudio.h> #include <stdexcept> -//#include <gri_logger.h> class audio_portaudio_source; typedef boost::shared_ptr<audio_portaudio_source> audio_portaudio_source_sptr; @@ -74,11 +73,13 @@ class audio_portaudio_source : public gr_sync_block { gr_buffer_sptr d_writer; // buffer used between work and callback gr_buffer_reader_sptr d_reader; - omni_semaphore d_ringbuffer_ready; // binary semaphore + + gruel::mutex d_ringbuffer_mutex; + gruel::condition_variable d_ringbuffer_cond; + bool d_ringbuffer_ready; // random stats int d_noverruns; // count of overruns - //gri_logger_sptr d_log; // handle to non-blocking logging instance void output_error_msg (const char *msg, int err); void bail (const char *msg, int err) throw (std::runtime_error); @@ -87,7 +88,7 @@ class audio_portaudio_source : public gr_sync_block { protected: audio_portaudio_source (int sampling_rate, const std::string device_name, - bool ok_to_block); + bool ok_to_block); public: ~audio_portaudio_source (); |