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
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
)
/// 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.
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);
return new ::FreeDV::AudioSink(parameter);
}
+ size_t
+ AudioSink::ready()
+ {
+ return SIZE_MAX;
+ }
+
#ifndef NO_INITIALIZERS
static bool
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)
{
}
+ size_t
+ BlankPanel::ready()
+ {
+ return 0;
+ }
+
UserInterface *
Driver::BlankPanel(const char * parameter, Interfaces * interfaces)
{
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;
};
/// 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.
};
/// 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);
/// 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;
--- /dev/null
+/// The I/O Device class.
+
+#include "drivers.h"
+
+namespace FreeDV {
+ IODevice::IODevice(const char * name, const char * parameters)
+ : Base(name, parameters)
+ {
+ }
+
+ IODevice::~IODevice()
+ {
+ }
+}
PTTConstant(const char * parameters);
virtual ~PTTConstant();
+ /// Return the amount of bytes ready for read.
+ size_t ready();
};
PTTConstant::PTTConstant(const char * parameters)
{
}
+ size_t
+ PTTConstant::ready()
+ {
+ return SIZE_MAX;
+ }
+
PTTInput *
Driver::PTTConstant(const char * parameter)
{
namespace FreeDV {
PTTInput::PTTInput(const char * name, const char * parameters)
- : Base(name, parameters)
+ : IODevice(name, parameters)
{
}
// Tests for the AudioSink class.
#include <drivers.h>
#include <gtest/gtest.h>
+#include <climits>
using namespace FreeDV;
}
};
+TEST_F(AudioSinkTest, AlwaysReady) {
+ EXPECT_EQ(SIZE_MAX, o->ready());
+}
+
TEST_F(AudioSinkTest, WriteReturnsSize) {
int16_t buffer[8];
--- /dev/null
+/// 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());
+}
#include <gtest/gtest.h>
#include <sstream>
#include <iostream>
+#include <climits>
using namespace FreeDV;
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.
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)
{
}
+ size_t
+ TextConstant::ready()
+ {
+ return SIZE_MAX;
+ }
+
TextInput *
Driver::TextConstant(const char * parameter)
{
namespace FreeDV {
TextInput::TextInput(const char * name, const char * parameters)
- : Base(name, parameters)
+ : IODevice(name, parameters)
{
}
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)
{
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)
{
namespace FreeDV {
UserInterface::UserInterface(const char * name, const char * parameters, Interfaces * interfaces)
- : Base(name, parameters)
+ : IODevice(name, parameters)
{
}