Convert gr-audio-portaudio to Boost via gruel
authorJohnathan Corgan <jcorgan@corganenterprises.com>
Tue, 27 Apr 2010 05:13:34 +0000 (22:13 -0700)
committerJohnathan Corgan <jcorgan@corganenterprises.com>
Tue, 27 Apr 2010 05:13:34 +0000 (22:13 -0700)
Remove omnithread dependency in build for gr-audio-portaudio
Remove unused debugging utility class in gnuradio-core (gri_logger)

config/grc_gr_audio_portaudio.m4
gnuradio-core/src/lib/io/Makefile.am
gnuradio-core/src/lib/io/gri_logger.cc [deleted file]
gnuradio-core/src/lib/io/gri_logger.h [deleted file]
gr-audio-portaudio/src/Makefile.am
gr-audio-portaudio/src/audio_portaudio_sink.cc
gr-audio-portaudio/src/audio_portaudio_sink.h
gr-audio-portaudio/src/audio_portaudio_source.cc
gr-audio-portaudio/src/audio_portaudio_source.h

index 08d71f8fb257ab9884f3b3b3bf406e213f5a2986..ff551b38a77df1f07928e72d96daf9a617cff8c3 100644 (file)
@@ -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
index 9eacd137d9b3fa27b3c0cb75faad2480e4fd14d2..c52554645779ef0d0f34398be28b7d86a4638ddb 100644 (file)
@@ -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 (file)
index 473a7c5..0000000
+++ /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 (file)
index 0a14145..0000000
+++ /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 */
index 20213d16b5950f748856ad9e66a0f577044f1070..1df6bbceaf546ddc1e72ae04f39d75ffb419a61f 100644 (file)
@@ -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 = \
index 2e48feb4af63410d1b376d33dfb9823b98f18f9f..65a38f9119011f4dc96bd66bc1a6a71e7bb08023 100644 (file)
@@ -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
index 1a0729799ff048400056f418b445c2c416d9d57e..71cbfcf9f011d0c72dbcb67ddf13b0abaad4ca78 100644 (file)
@@ -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
index 9e883ad8a36cda1b977d99dadd18c23f9c9f5526..484b7f1e541bb42c86d84937c801ec61319b8c2f 100644 (file)
@@ -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
index 3102db739c8a41a497d583ed718ef988480c137a..31e70a12779b257f2c72078c6d881cef9cbc119e 100644 (file)
@@ -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
  * 
 
 #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 ();