Add I/O ready indication. New tests for blank_panel.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 21 Jan 2014 03:34:02 +0000 (03:34 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 21 Jan 2014 03:34:02 +0000 (03:34 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1379 01035d8c-6547-0410-b346-abe4f91aad63

14 files changed:
freedv-server/CMakeLists.txt
freedv-server/source/audio_sink.cpp
freedv-server/source/blank_panel.cpp
freedv-server/source/drivers.h
freedv-server/source/io_device.cpp [new file with mode: 0644]
freedv-server/source/ptt_constant.cpp
freedv-server/source/ptt_input.cpp
freedv-server/source/test/audio_sink.cpp
freedv-server/source/test/blank_panel.cpp [new file with mode: 0644]
freedv-server/source/test/tone.cpp
freedv-server/source/text_constant.cpp
freedv-server/source/text_input.cpp
freedv-server/source/tone.cpp
freedv-server/source/user_interface.cpp

index e8ec32511af1aa601a2ccfecaa53698b6bfe3455..b70ca1631cdac659cf25c0cd4a2fc8d014537d9d 100644 (file)
@@ -98,6 +98,7 @@ set(Compile.sources
   source/driver_manager.cpp
   source/event_handler.cpp
   source/interfaces.cpp
+  source/io_device.cpp
   source/keying.cpp
   source/keying_sink.cpp
   source/libevent.cpp
@@ -126,6 +127,7 @@ set(Optional.sources
 set(Test.sources
   source/test/audio_sink.cpp
   source/test/base.cpp
+  source/test/blank_panel.cpp
   source/test/keying_sink.cpp
   source/test/tone.cpp
 )
index e0b41f1013e0934af941efaed05ce23dc71b250c..560db6b04c197ba68a4df1cf4a2aede8fa1cdcc3 100644 (file)
@@ -1,6 +1,7 @@
 /// The AudioSink driver, called as "sink", discards the audio, for testing.
 
 #include "drivers.h"
+#include <climits>
 
 namespace FreeDV {
   /// Audio output "sink", discards the audio, for testing.
@@ -11,6 +12,11 @@ namespace FreeDV {
                AudioSink(const char * parameters);
                ~AudioSink();
 
+       /// Return the number of audio samples the device can handle in
+       /// a write without blocking. This version always returns SIZE_MAX.
+        virtual size_t
+               ready();
+
         /// Write audio into the "short" type.
        virtual std::size_t
                write16(const int16_t * array, std::size_t length);
@@ -38,6 +44,12 @@ namespace FreeDV {
     return new ::FreeDV::AudioSink(parameter);
   }
 
+  size_t
+  AudioSink::ready()
+  {
+    return SIZE_MAX;
+  }
+
 #ifndef NO_INITIALIZERS
 
   static bool
index a9444fdf76802e936dc064fae89d388310f72ec1..9127a18165e966482d3c84638f7445259c435a2d 100644 (file)
@@ -11,6 +11,9 @@ namespace FreeDV {
                        BlankPanel(const char * parameter, Interfaces * interfaces);
     virtual            ~BlankPanel();
     
+    /// Return the amount of bytes ready for read. In this case, it always
+    /// returns 0.
+    size_t     ready();
   };
 
   BlankPanel::BlankPanel(const char * parameter, Interfaces * interfaces)
@@ -22,6 +25,12 @@ namespace FreeDV {
   {
   }
 
+  size_t
+  BlankPanel::ready()
+  {
+    return 0;
+  }
+
   UserInterface *
   Driver::BlankPanel(const char * parameter, Interfaces * interfaces)
   {
index 61473626b0be95f2db0ae87c92160ddcb2f74191..e7e09f663b8b6ccdc7d451a3995cb4da8aa35798 100644 (file)
@@ -81,8 +81,31 @@ namespace FreeDV {
     return base.print(stream);
   }
   
+  /// Virtual base class for all drivers that perform non-blocking I/O.
+  /// These are AudioInput and AudioOutput, PTTInput, TextInput, and
+  /// UserInterface.
+  /// Keying is assumed to never need to block.
+  class IODevice : public ::FreeDV::Base {
+  protected:
+                       IODevice(const char * name, const char * parameters);
+
+  public:
+    /// Return the number of audio samples, or bytes for devices other than
+    /// audio interfaces, that can be read or written. Return zero if there
+    /// is not enough readable or writable data to do some work, for example
+    /// if the device is a PTT input and the internal driver detects less
+    /// readable data than necessary to read the HID status.
+    ///
+    /// All drivers present a unidirectional interface.
+    /// If the underlying device is bidirectional that detail is hidden and
+    /// we present one or more separate read and write drivers.
+    virtual size_t     ready() = 0;
+
+    virtual            ~IODevice() = 0;
+  };
+
   /// Virtual base class for AudioInput and AudioOutput.
-  class AudioDevice : public ::FreeDV::Base {
+  class AudioDevice : public ::FreeDV::IODevice {
   protected:
     /// The master volume control for the device.
     float              master_amplitude;
@@ -320,7 +343,7 @@ namespace FreeDV {
   };
 
   /// Push-to-talk input driver.
-  class PTTInput : public ::FreeDV::Base {
+  class PTTInput : public ::FreeDV::IODevice {
   private:
     /// Coroutine to be called when the sense of the push-to-talk switch
     /// changes.
@@ -347,7 +370,7 @@ namespace FreeDV {
   };
 
   /// Driver for the text message source function.
-  class TextInput : public ::FreeDV::Base {
+  class TextInput : public ::FreeDV::IODevice {
   protected:
     /// The child class calls this member in its parent to set the text.
     void               set(const char * text);
@@ -372,7 +395,7 @@ namespace FreeDV {
   /// There must be inputs and callbacks for many things here.
   /// UserInterfaces may provide their own drivers for microphone,
   /// loudspeaker, TextInput, both forms of PTT, and EventHandler.
-  class UserInterface : public ::FreeDV::Base {
+  class UserInterface : public ::FreeDV::IODevice {
   protected:
     /// The external Interfaces object.
     Interfaces *       interfaces;
diff --git a/freedv-server/source/io_device.cpp b/freedv-server/source/io_device.cpp
new file mode 100644 (file)
index 0000000..146312f
--- /dev/null
@@ -0,0 +1,14 @@
+/// The I/O Device class.
+
+#include "drivers.h"
+
+namespace FreeDV {
+  IODevice::IODevice(const char * name, const char * parameters)
+  : Base(name, parameters)
+  {
+  }
+
+  IODevice::~IODevice()
+  {
+  }
+}
index 474d376b3790d87b794b43a020f046a80960f5e8..d15c6181b7a88e24a9ea9a6dceb4f27dc1b2d216 100644 (file)
@@ -10,6 +10,8 @@ namespace FreeDV {
                        PTTConstant(const char * parameters);
     virtual            ~PTTConstant();
     
+    /// Return the amount of bytes ready for read.
+    size_t     ready();
   };
 
   PTTConstant::PTTConstant(const char * parameters)
@@ -21,6 +23,12 @@ namespace FreeDV {
   {
   }
 
+  size_t
+  PTTConstant::ready()
+  {
+    return SIZE_MAX;
+  }
+
   PTTInput *
   Driver::PTTConstant(const char * parameter)
   {
index 3f79a717e763da730ad2b2eda51436a4dc50ef0a..447790ba12b2a25e83c0de05b1b025b505b5be38 100644 (file)
@@ -4,7 +4,7 @@
 
 namespace FreeDV {
   PTTInput::PTTInput(const char * name, const char * parameters)
-  : Base(name, parameters)
+  : IODevice(name, parameters)
   {
   }
 
index 8d1943f97d86cceb80b7f09b89849d8b9c633ea1..4f86a1c3a61f4f6715d0ec8af109d7cf14f801b4 100644 (file)
@@ -1,6 +1,7 @@
 // Tests for the AudioSink class.
 #include <drivers.h>
 #include <gtest/gtest.h>
+#include <climits>
 
 using namespace FreeDV;
 
@@ -22,6 +23,10 @@ protected:
   }
 };
 
+TEST_F(AudioSinkTest, AlwaysReady) {
+  EXPECT_EQ(SIZE_MAX, o->ready());
+}
+
 TEST_F(AudioSinkTest, WriteReturnsSize) {
   int16_t      buffer[8];
 
diff --git a/freedv-server/source/test/blank_panel.cpp b/freedv-server/source/test/blank_panel.cpp
new file mode 100644 (file)
index 0000000..751016f
--- /dev/null
@@ -0,0 +1,31 @@
+/// Tests for the BlankPanel class.
+#include <drivers.h>
+#include <gtest/gtest.h>
+#include <climits>
+
+using namespace FreeDV;
+
+class BlankPanelTest : public ::testing::Test {
+protected:
+       UserInterface * u;
+        Interfaces *   i;
+
+       BlankPanelTest()
+       : u(0)
+       {
+       }
+
+  void SetUp() {
+    i = new Interfaces();
+    u = Driver::BlankPanel("", i);
+  }
+
+  void TearDown() {
+    delete u;
+    delete i;
+  }
+};
+
+TEST_F(BlankPanelTest, NeverReady) {
+  EXPECT_EQ(0, u->ready());
+}
index 36998df77def04280c6d7369b6ca8e21f0ad9608..a64cc7f70e9f0359503aec1e8982d80848764056 100644 (file)
@@ -3,6 +3,7 @@
 #include <gtest/gtest.h>
 #include <sstream>
 #include <iostream>
+#include <climits>
 
 using namespace FreeDV;
 
@@ -45,6 +46,10 @@ TEST_F(ToneTest, EnforcesNormalization) {
   EXPECT_NO_THROW(i->amplitude(1.0));
 }
 
+TEST_F(ToneTest, AlwaysReady) {
+  EXPECT_EQ(SIZE_MAX, i->ready());
+}
+
 // Maximum positive value of a signed 16-bit integer.
 const int16_t  MaxS16((1 << 15) - 1);
 // Half of the maximum positive value of a signed 16-bit integer.
index adee5063558c39867ecf7d573dc203a85b5f9c1c..5923c9c4d1973fb03fe552b7d96032a218487e99 100644 (file)
@@ -10,6 +10,9 @@ namespace FreeDV {
                        TextConstant(const char * parameter);
     virtual            ~TextConstant();
     
+    /// Return the amount of bytes ready for read. In this case, it always
+    /// returns SIZE_MAX.
+    size_t     ready();
   };
 
   TextConstant::TextConstant(const char * parameters)
@@ -21,6 +24,12 @@ namespace FreeDV {
   {
   }
 
+  size_t
+  TextConstant::ready()
+  {
+    return SIZE_MAX;
+  }
+
   TextInput *
   Driver::TextConstant(const char * parameter)
   {
index 740bebd1a3fbd4a2cadb16c04065d97548189d08..54c979f7db24b8c1365ab34127fd9292342d27ee 100644 (file)
@@ -4,7 +4,7 @@
 
 namespace FreeDV {
   TextInput::TextInput(const char * name, const char * parameters)
-  : Base(name, parameters)
+  : IODevice(name, parameters)
   {
   }
 
index dd4a37c19505e7cdc13e9677f9cea7cc6bee0b80..a8bb3305c68890b058b418acf9ab0a9c6044b84e 100644 (file)
@@ -18,39 +18,22 @@ namespace FreeDV {
 
     tone_info  tones[101];
 
-    /// Generate a sine wave.
-    float
-    sine_wave(float frequency, unsigned int step)
-    {
-      // The number of samples per cycle for the given frequency and sample
-      // rate.
-      const float      samplesPerCycle = SampleRate / frequency;
-
-      // Add 1/4 turn to the step so that at the Nyquist frequency we
-      // render the peaks rather than the zero crossings.
-      const float      bias = step + (samplesPerCycle / 4);
-
-      // Angular measure where 1.0 = 360 degrees.
-      const float      portionOfCycle = fmod(bias, samplesPerCycle) / samplesPerCycle;
-
-      // Convert to radians.
-      const float radians = portionOfCycle * M_PI * 2;
-
-      const float sine = sin(radians);
-
-      return sine;
-    }
+    /// Return the amount of audio samples for read. In this case, it always
+    /// returns SIZE_MAX.
+    size_t     ready();
 
+    /// Generate a sine wave.
+    float      sine_wave(float frequency, unsigned int step);
   public:
     /// Instantiate the tone driver.
-                       Tone(const char * parameter);
+                       Tone(const char * parameters);
+
     virtual            ~Tone();
     
     // Read audio into the "short" type.
     virtual std::size_t        read16(int16_t * array, std::size_t length);
   };
 
-
   Tone::Tone(const char * parameters)
   : AudioInput("tone", parameters), clock(0)
   {
@@ -135,6 +118,34 @@ namespace FreeDV {
     clock = (clock + length) % SampleRate;
   }
 
+  size_t
+  Tone::ready()
+  {
+    return SIZE_MAX;
+  }
+
+  float
+  Tone::sine_wave(float frequency, unsigned int step)
+  {
+    // The number of samples per cycle for the given frequency and sample
+    // rate.
+    const float        samplesPerCycle = SampleRate / frequency;
+
+    // Add 1/4 turn to the step so that at the Nyquist frequency we
+    // render the peaks rather than the zero crossings.
+    const float        bias = step + (samplesPerCycle / 4);
+
+    // Angular measure where 1.0 = 360 degrees.
+    const float        portionOfCycle = fmod(bias, samplesPerCycle) / samplesPerCycle;
+
+    // Convert to radians.
+    const float radians = portionOfCycle * M_PI * 2;
+
+    const float sine = sin(radians);
+
+    return sine;
+  }
+
   AudioInput *
   Driver::Tone(const char * parameter)
   {
index 119d7295b6e8454aa09bcc602a23a41743b9e80d..5a74388e10e78e1c9c5e3e342d241c1369777639 100644 (file)
@@ -4,7 +4,7 @@
 
 namespace FreeDV {
   UserInterface::UserInterface(const char * name, const char * parameters, Interfaces * interfaces)
-  : Base(name, parameters)
+  : IODevice(name, parameters)
   {
   }