[DEV] add virtual interface

This commit is contained in:
Edouard DUPIN 2015-02-12 22:08:23 +01:00
parent 1e10cc276b
commit a086674189
7 changed files with 99 additions and 32 deletions

View File

@ -12,7 +12,7 @@
resampling-option:"quality=10" resampling-option:"quality=10"
}, },
feedback:{ feedback:{
io:"input", io:"feedback", # note : Feedback is plugged on an output not an input
map-on:"speaker", map-on:"speaker",
resampling-type:"speexdsp", resampling-type:"speexdsp",
resampling-option:"quality=10" resampling-option:"quality=10"
@ -22,8 +22,9 @@
map-on:"speaker", map-on:"speaker",
resampling-type:"speexdsp", resampling-type:"speexdsp",
resampling-option:"quality=10", resampling-option:"quality=10",
aec-map-on:"microphone", the second input of the AEC (get a single # specific case for AEC : only 3 options
aec-type:"airtio-remover", # some type is "airtio-remover", aec-map-on:"microphone", # the second input of the AEC (get a single)
aec-type:"river-remover", # some type is "airtio-remover",
aec-option:"mode=cutter" aec-option:"mode=cutter"
} }
} }

View File

@ -27,18 +27,27 @@ river::Interface::Interface(void) :
} }
bool river::Interface::init(const std::string& _name, bool river::Interface::init(const std::string& _name,
float _freq, float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<river::io::Node>& _node, const std::shared_ptr<river::io::Node>& _node,
bool _isInput) { const std::shared_ptr<const ejson::Object>& _config) {
m_name = _name; m_name = _name;
m_node = _node; m_node = _node;
m_freq = _freq; m_freq = _freq;
m_map = _map; m_map = _map;
m_format = _format; m_format = _format;
m_volume = 0.0f; m_volume = 0.0f;
m_isInput = _isInput; m_config = _config;
m_mode = river::modeInterface_unknow;
std::string type = m_config->getStringValue("io", "error");
if (type == "output") {
m_mode = river::modeInterface_output;
} else if (type == "input") {
m_mode = river::modeInterface_input;
} else if (type == "feedback") {
m_mode = river::modeInterface_feedback;
}
// register interface to be notify from the volume change. // register interface to be notify from the volume change.
m_node->registerAsRemote(shared_from_this()); m_node->registerAsRemote(shared_from_this());
// Create convertion interface // Create convertion interface
@ -75,13 +84,13 @@ bool river::Interface::init(const std::string& _name,
} }
std::shared_ptr<river::Interface> river::Interface::create(const std::string& _name, std::shared_ptr<river::Interface> river::Interface::create(const std::string& _name,
float _freq, float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<river::io::Node>& _node, const std::shared_ptr<river::io::Node>& _node,
bool _isInput) { const std::shared_ptr<const ejson::Object>& _config) {
std::shared_ptr<river::Interface> out = std::shared_ptr<river::Interface>(new river::Interface()); std::shared_ptr<river::Interface> out = std::shared_ptr<river::Interface>(new river::Interface());
out->init(_name, _freq, _map, _format, _node, _isInput); out->init(_name, _freq, _map, _format, _node, _config);
return out; return out;
} }

View File

@ -19,11 +19,18 @@
#include <drain/EndPointCallback.h> #include <drain/EndPointCallback.h>
#include <drain/EndPointWrite.h> #include <drain/EndPointWrite.h>
#include <memory> #include <memory>
#include <ejson/ejson.h>
namespace river { namespace river {
namespace io { namespace io {
class Node; class Node;
} }
enum modeInterface {
modeInterface_unknow,
modeInterface_input,
modeInterface_output,
modeInterface_feedback,
};
class Interface : public std::enable_shared_from_this<Interface> { class Interface : public std::enable_shared_from_this<Interface> {
friend class io::Node; friend class io::Node;
friend class Manager; friend class Manager;
@ -35,6 +42,7 @@ namespace river {
std::vector<audio::channel> m_map; std::vector<audio::channel> m_map;
audio::format m_format; audio::format m_format;
drain::Process m_process; drain::Process m_process;
std::shared_ptr<const ejson::Object> m_config;
protected: protected:
std::string m_name; std::string m_name;
public: public:
@ -42,13 +50,10 @@ namespace river {
return m_name; return m_name;
}; };
protected: protected:
bool m_isInput; enum modeInterface m_mode;
public: public:
bool isInput() { enum modeInterface getMode() {
return m_isInput; return m_mode;
}
bool isOutput() {
return !m_isInput;
} }
protected: protected:
/** /**
@ -60,7 +65,7 @@ namespace river {
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<river::io::Node>& _node, const std::shared_ptr<river::io::Node>& _node,
bool _isInput); const std::shared_ptr<const ejson::Object>& _config);
public: public:
/** /**
* @brief Destructor * @brief Destructor
@ -71,7 +76,7 @@ namespace river {
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<river::io::Node>& _node, const std::shared_ptr<river::io::Node>& _node,
bool _isInput); const std::shared_ptr<const ejson::Object>& _config);
/** /**
* @brief set the read/write mode enable. * @brief set the read/write mode enable.
*/ */

View File

@ -23,7 +23,10 @@ std::shared_ptr<river::Manager> river::Manager::create(const std::string& _appli
river::Manager::Manager(const std::string& _applicationUniqueId) : river::Manager::Manager(const std::string& _applicationUniqueId) :
m_applicationUniqueId(_applicationUniqueId), m_applicationUniqueId(_applicationUniqueId),
m_listOpenInterface() { m_listOpenInterface() {
// TODO : Maybe create a single interface property (and all get the same ...)
if (m_config.load("DATA:virtual.json") == false) {
RIVER_ERROR("you must set a basic configuration file for virtual configuration: DATA:virtual.json");
}
} }
river::Manager::~Manager() { river::Manager::~Manager() {
@ -33,13 +36,30 @@ river::Manager::~Manager() {
std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamInput() { std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamInput() {
std::vector<std::pair<std::string,std::string> > output; std::vector<std::pair<std::string,std::string> > output;
//output.push_back(std::make_pair<std::string,std::string>("default", "48000 Hz, 16 bits, 2 channels: Default input ")); for (auto &it : m_config.getKeys()) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(it);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if ( type == "input"
|| type == "feedback") {
output.push_back(std::make_pair<std::string,std::string>(std::string(it), std::string("---")));
}
}
}
return output; return output;
} }
std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamOutput() { std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamOutput() {
std::vector<std::pair<std::string,std::string> > output; std::vector<std::pair<std::string,std::string> > output;
//output.push_back(std::make_pair<std::string,std::string>("default", "48000 Hz, 16 bits, 2 channels: Default output ")); for (auto &it : m_config.getKeys()) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(it);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if (type == "output") {
output.push_back(std::make_pair<std::string,std::string>(std::string(it), std::string("---")));
}
}
}
return output; return output;
} }
@ -61,13 +81,26 @@ std::shared_ptr<river::Interface> river::Manager::createOutput(float _freq,
audio::format _format, audio::format _format,
const std::string& _streamName, const std::string& _streamName,
const std::string& _name) { const std::string& _name) {
// check if the output exist
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(_streamName);
if (tmppp == nullptr) {
RIVER_ERROR("can not open a non existance virtual input: '" << _streamName << "' not present in : " << m_config.getKeys());
return nullptr;
}
// check if it is an Output:
std::string type = tmppp->getStringValue("io", "error");
if (type != "output") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' configured has : " << type);
return nullptr;
}
// get global hardware interface: // get global hardware interface:
std::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance(); std::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
// get the output or input channel : // get the output or input channel :
std::shared_ptr<river::io::Node> node = manager->getNode(_streamName); std::shared_ptr<river::io::Node> node = manager->getNode(_streamName);
// create user iterface: // create user iterface:
std::shared_ptr<river::Interface> interface; std::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, false); interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp);
// store it in a list (needed to apply some parameters). // store it in a list (needed to apply some parameters).
m_listOpenInterface.push_back(interface); m_listOpenInterface.push_back(interface);
return interface; return interface;
@ -78,13 +111,26 @@ std::shared_ptr<river::Interface> river::Manager::createInput(float _freq,
audio::format _format, audio::format _format,
const std::string& _streamName, const std::string& _streamName,
const std::string& _name) { const std::string& _name) {
// check if the output exist
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(_streamName);
if (tmppp == nullptr) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _streamName << "' not present in : " << m_config.getKeys());
return nullptr;
}
// check if it is an Output:
std::string type = tmppp->getStringValue("io", "error");
if ( type != "input"
&& type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' configured has : " << type);
return nullptr;
}
// get global hardware interface: // get global hardware interface:
std::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance(); std::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
// get the output or input channel : // get the output or input channel :
std::shared_ptr<river::io::Node> node = manager->getNode(_streamName); std::shared_ptr<river::io::Node> node = manager->getNode(_streamName);
// create user iterface: // create user iterface:
std::shared_ptr<river::Interface> interface; std::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, true); interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp);
// store it in a list (needed to apply some parameters). // store it in a list (needed to apply some parameters).
m_listOpenInterface.push_back(interface); m_listOpenInterface.push_back(interface);
return interface; return interface;

View File

@ -13,6 +13,7 @@
#include <river/Interface.h> #include <river/Interface.h>
#include <audio/format.h> #include <audio/format.h>
#include <audio/channel.h> #include <audio/channel.h>
#include <ejson/ejson.h>
namespace river { namespace river {
/** /**
@ -20,6 +21,7 @@ namespace river {
*/ */
class Manager { class Manager {
private: private:
ejson::Document m_config; // virtual configuration
const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface. const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface.
std::vector<std::weak_ptr<river::Interface> > m_listOpenInterface; //!< List of all open Stream. std::vector<std::weak_ptr<river::Interface> > m_listOpenInterface; //!< List of all open Stream.
protected: protected:

View File

@ -16,6 +16,7 @@ river::io::Manager::Manager() {
if (m_config.load("DATA:hardware.json") == false) { if (m_config.load("DATA:hardware.json") == false) {
RIVER_ERROR("you must set a basic configuration file for harware configuration: DATA:hardware.json"); RIVER_ERROR("you must set a basic configuration file for harware configuration: DATA:hardware.json");
} }
// TODO : Load virtual.json and check if all is correct ...
}; };
@ -25,8 +26,8 @@ std::shared_ptr<river::io::Manager> river::io::Manager::getInstance() {
} }
std::shared_ptr<river::io::Node> river::io::Manager::getNode(const std::string& _name) { std::shared_ptr<river::io::Node> river::io::Manager::getNode(const std::string& _name) {
for (size_t iii=0; iii< m_list.size(); ++iii) { for (auto &it : m_list) {
std::shared_ptr<river::io::Node> tmppp = m_list[iii].lock(); std::shared_ptr<river::io::Node> tmppp = it.lock();
if ( tmppp != nullptr if ( tmppp != nullptr
&& _name == tmppp->getName()) { && _name == tmppp->getName()) {
return tmppp; return tmppp;

View File

@ -69,7 +69,7 @@ int32_t river::io::Node::airtAudioCallback(void* _outputBuffer,
if (it == nullptr) { if (it == nullptr) {
continue; continue;
} }
if (it->isOutput() == false) { if (it->getMode() != river::modeInterface_output) {
continue; continue;
} }
RIVER_VERBOSE(" IO name="<< it->getName()); RIVER_VERBOSE(" IO name="<< it->getName());
@ -91,7 +91,7 @@ int32_t river::io::Node::airtAudioCallback(void* _outputBuffer,
if (it == nullptr) { if (it == nullptr) {
continue; continue;
} }
if (it->isInput() == false) { if (it->getMode() != river::modeInterface_feedback) {
continue; continue;
} }
RIVER_VERBOSE(" IO name="<< it->getName() << " (feedback)"); RIVER_VERBOSE(" IO name="<< it->getName() << " (feedback)");
@ -106,6 +106,9 @@ int32_t river::io::Node::airtAudioCallback(void* _outputBuffer,
if (it == nullptr) { if (it == nullptr) {
continue; continue;
} }
if (it->getMode() != river::modeInterface_input) {
continue;
}
RIVER_INFO(" IO name="<< it->getName()); RIVER_INFO(" IO name="<< it->getName());
it->systemNewInputData(_time, inputBuffer, _nbChunk); it->systemNewInputData(_time, inputBuffer, _nbChunk);
} }