audio-river/audio/river/Interface.cpp

523 lines
19 KiB
C++
Raw Normal View History

2015-01-25 22:17:06 +01:00
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
2015-01-25 22:17:06 +01:00
*/
2017-09-26 15:57:44 +02:00
#include <audio/river/debug.hpp>
#include <audio/river/Interface.hpp>
#include <audio/river/io/Node.hpp>
2016-10-02 22:19:26 +02:00
#include <audio/drain/EndPointCallback.hpp>
#include <audio/drain/EndPointWrite.hpp>
#include <audio/drain/EndPointRead.hpp>
#include <audio/drain/Volume.hpp>
2015-01-25 22:17:06 +01:00
2018-10-23 22:19:32 +02:00
audio::river::Interface::Interface(void) {
2015-02-18 23:37:09 +01:00
static uint32_t uid = 0;
m_uid = uid++;
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
bool audio::river::Interface::init(float _freq,
2017-08-28 00:08:50 +02:00
const etk::Vector<audio::channel>& _map,
2016-07-19 21:43:58 +02:00
audio::format _format,
ememory::SharedPtr<audio::river::io::Node> _node,
const ejson::Object& _config) {
2017-08-28 00:08:50 +02:00
etk::Vector<audio::channel> map(_map);
2015-01-25 22:17:06 +01:00
m_node = _node;
2015-02-12 22:08:23 +01:00
m_config = _config;
2015-04-11 09:38:30 +02:00
m_mode = audio::river::modeInterface_unknow;
2017-08-28 00:08:50 +02:00
etk::String type = m_config["io"].toString().get("error");
2015-03-18 21:48:57 +01:00
static int32_t uid=0;
2017-08-28 00:08:50 +02:00
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::toString(uid++);
2015-02-12 22:08:23 +01:00
if (type == "output") {
2015-04-11 09:38:30 +02:00
m_mode = audio::river::modeInterface_output;
2015-02-12 22:08:23 +01:00
} else if (type == "input") {
2015-04-11 09:38:30 +02:00
m_mode = audio::river::modeInterface_input;
2015-02-12 22:08:23 +01:00
} else if (type == "feedback") {
2015-04-11 09:38:30 +02:00
m_mode = audio::river::modeInterface_feedback;
2015-02-12 22:08:23 +01:00
}
2015-02-04 21:08:06 +01:00
// register interface to be notify from the volume change.
2016-07-19 21:43:58 +02:00
m_node->registerAsRemote(sharedFromThis());
2015-03-04 22:48:04 +01:00
if (map.size() == 0) {
RIVER_INFO("Select auto map system ...");
map = m_node->getInterfaceFormat().getMap();
RIVER_INFO(" ==> " << map);
}
2015-01-25 22:17:06 +01:00
// Create convertion interface
2015-02-17 21:08:15 +01:00
if ( m_node->isInput() == true
2015-04-11 09:38:30 +02:00
&& m_mode == audio::river::modeInterface_input) {
2015-02-09 21:44:32 +01:00
m_process.setInputConfig(m_node->getInterfaceFormat());
2015-03-05 22:14:07 +01:00
// Add volume only if the Low level has a volume (otherwise it will be added by the application)
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
2018-06-19 22:13:48 +02:00
if (tmpVolume != null) {
2015-03-05 22:14:07 +01:00
// add all time the volume stage :
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
2015-03-05 22:14:07 +01:00
//algo->setInputFormat(m_node->getInterfaceFormat());
algo->setName("volume");
m_process.pushBack(algo);
RIVER_INFO(" add volume for node");
algo->addVolumeStage(tmpVolume);
}
2015-04-11 09:38:30 +02:00
m_process.setOutputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
2015-02-17 21:08:15 +01:00
} else if ( m_node->isOutput() == true
2015-04-11 09:38:30 +02:00
&& m_mode == audio::river::modeInterface_output) {
m_process.setInputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
2015-03-05 22:14:07 +01:00
// Add volume only if the Low level has a volume (otherwise it will be added by the application)
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
2018-06-19 22:13:48 +02:00
if (tmpVolume != null) {
2015-03-05 22:14:07 +01:00
// add all time the volume stage :
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
2015-03-05 22:14:07 +01:00
//algo->setOutputFormat(m_node->getInterfaceFormat());
algo->setName("volume");
m_process.pushBack(algo);
RIVER_INFO(" add volume for node");
algo->addVolumeStage(tmpVolume);
}
2015-02-09 21:44:32 +01:00
m_process.setOutputConfig(m_node->getInterfaceFormat());
2015-02-17 21:08:15 +01:00
} else if ( m_node->isOutput() == true
2015-04-11 09:38:30 +02:00
&& m_mode == audio::river::modeInterface_feedback) {
2015-02-17 21:08:15 +01:00
m_process.setInputConfig(m_node->getHarwareFormat());
// note : feedback has no volume stage ...
2015-04-11 09:38:30 +02:00
m_process.setOutputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
2015-02-17 21:08:15 +01:00
} else {
RIVER_ERROR("Can not link virtual interface with type : " << m_mode << " to a hardware interface " << (m_node->isInput()==true?"input":"output"));
return false;
2015-01-25 22:17:06 +01:00
}
2015-01-26 22:04:29 +01:00
return true;
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::river::Interface> audio::river::Interface::create(float _freq,
2017-09-26 15:57:44 +02:00
const etk::Vector<audio::channel>& _map,
audio::format _format,
const ememory::SharedPtr<audio::river::io::Node>& _node,
const ejson::Object& _config) {
2017-11-07 13:38:04 +01:00
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(ETK_NEW(audio::river::Interface));
2015-03-12 22:28:15 +01:00
out->init(_freq, _map, _format, _node, _config);
2015-01-26 22:04:29 +01:00
return out;
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
audio::river::Interface::~Interface() {
2015-01-28 22:07:11 +01:00
//stop(true, true);
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2016-07-19 21:43:58 +02:00
//m_node->interfaceRemove(sharedFromThis());
2015-01-25 22:17:06 +01:00
}
2015-02-01 22:21:03 +01:00
/*
2015-04-11 09:38:30 +02:00
bool audio::river::Interface::hasEndPoint() {
2015-02-01 22:21:03 +01:00
}
*/
2015-04-11 09:38:30 +02:00
void audio::river::Interface::setReadwrite() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-02-09 21:44:32 +01:00
m_process.removeAlgoDynamic();
2015-04-11 09:38:30 +02:00
if (m_process.hasType<audio::drain::EndPoint>() ) {
RIVER_ERROR("Endpoint is already present ==> can not change");
2015-02-01 22:21:03 +01:00
return;
}
2017-09-26 15:57:44 +02:00
RIVER_WARNING("Add output ReadWrite");
2015-02-01 22:21:03 +01:00
if (m_node->isInput() == true) {
2015-04-11 09:38:30 +02:00
m_process.removeIfLast<audio::drain::EndPoint>();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = audio::drain::EndPointRead::create();
2015-02-09 21:44:32 +01:00
m_process.pushBack(algo);
2015-02-01 22:21:03 +01:00
} else {
2015-04-11 09:38:30 +02:00
m_process.removeIfFirst<audio::drain::EndPoint>();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = audio::drain::EndPointWrite::create();
2015-02-09 21:44:32 +01:00
m_process.pushFront(algo);
2015-02-01 22:21:03 +01:00
}
}
2015-01-25 22:17:06 +01:00
2015-04-11 09:38:30 +02:00
void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _function) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-04-11 09:38:30 +02:00
if (m_mode != audio::river::modeInterface_output) {
2015-03-04 22:15:35 +01:00
RIVER_ERROR("Can not set output endpoint on other than a output IO");
return;
}
2017-09-26 15:57:44 +02:00
RIVER_WARNING("Add output callback");
2015-02-09 21:44:32 +01:00
m_process.removeAlgoDynamic();
2015-04-11 09:38:30 +02:00
m_process.removeIfFirst<audio::drain::EndPoint>();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
2015-02-09 21:44:32 +01:00
m_process.pushFront(algo);
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::setInputCallback(audio::drain::recordFunction _function) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-04-11 09:38:30 +02:00
if (m_mode == audio::river::modeInterface_output) {
2015-03-04 22:15:35 +01:00
RIVER_ERROR("Can not set output endpoint on other than a input or feedback IO");
return;
}
2017-09-26 15:57:44 +02:00
RIVER_WARNING("Add input callback");
2015-02-09 21:44:32 +01:00
m_process.removeAlgoDynamic();
2015-04-11 09:38:30 +02:00
m_process.removeIfLast<audio::drain::EndPoint>();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
2015-02-09 21:44:32 +01:00
m_process.pushBack(algo);
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::setWriteCallback(audio::drain::playbackFunctionWrite _function) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-04-11 09:38:30 +02:00
if (m_mode != audio::river::modeInterface_output) {
2015-03-04 22:15:35 +01:00
RIVER_ERROR("Can not set output endpoint on other than a output IO");
return;
}
2017-09-26 15:57:44 +02:00
RIVER_WARNING("Add output Write");
2015-02-09 21:44:32 +01:00
m_process.removeAlgoDynamic();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
2015-01-27 22:47:09 +01:00
return;
}
algo->setCallback(_function);
}
2015-01-25 22:17:06 +01:00
2015-04-13 21:49:48 +02:00
void audio::river::Interface::start(const audio::Time& _time) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
RIVER_DEBUG("start [BEGIN]");
2015-02-09 21:44:32 +01:00
m_process.updateInterAlgo();
2016-07-19 21:43:58 +02:00
m_node->interfaceAdd(sharedFromThis());
RIVER_DEBUG("start [ END ]");
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::stop(bool _fast, bool _abort) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
RIVER_DEBUG("stop [BEGIN]");
2016-07-19 21:43:58 +02:00
m_node->interfaceRemove(sharedFromThis());
RIVER_DEBUG("stop [ END]");
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::abort() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
RIVER_DEBUG("abort [BEGIN]");
2015-01-25 22:17:06 +01:00
// TODO :...
RIVER_DEBUG("abort [ END ]");
2015-01-25 22:17:06 +01:00
}
2017-09-14 00:59:21 +02:00
bool audio::river::Interface::setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value) {
RIVER_DEBUG("setParameter [BEGIN] : '" << _filter << "':'" << _parameter << "':'" << _value << "'");
2015-01-30 21:44:36 +01:00
bool out = false;
if ( _filter == "volume"
&& _parameter != "FLOW") {
RIVER_ERROR("Interface is not allowed to modify '" << _parameter << "' Volume just allowed to modify 'FLOW' volume");
return false;
2015-01-30 21:44:36 +01:00
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return false;
}
out = algo->setParameter(_parameter, _value);
RIVER_DEBUG("setParameter [ END ] : '" << out << "'");
2015-01-30 21:44:36 +01:00
return out;
2015-01-25 22:17:06 +01:00
}
2017-09-14 00:59:21 +02:00
etk::String audio::river::Interface::getParameter(const etk::String& _filter, const etk::String& _parameter) const {
RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'");
2017-08-28 00:08:50 +02:00
etk::String out;
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]";
}
out = algo->getParameter(_parameter);
RIVER_DEBUG("getParameter [ END ] : '" << out << "'");
2015-01-30 21:44:36 +01:00
return out;
2015-01-25 22:17:06 +01:00
}
2017-09-14 00:59:21 +02:00
etk::String audio::river::Interface::getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const {
RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'");
2017-08-28 00:08:50 +02:00
etk::String out;
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]";
}
out = algo->getParameterProperty(_parameter);
RIVER_DEBUG("getParameterProperty [ END ] : '" << out << "'");
2015-01-30 21:44:36 +01:00
return out;
2015-01-25 22:17:06 +01:00
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-02-09 21:44:32 +01:00
m_process.updateInterAlgo();
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
2015-01-25 22:17:06 +01:00
return;
}
algo->write(_value, _nbChunk);
}
2015-01-27 21:01:52 +01:00
#if 0
2015-01-25 22:17:06 +01:00
// TODO : add API aCCess mutex for Read and write...
2017-08-28 00:08:50 +02:00
etk::Vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
2015-01-25 22:17:06 +01:00
// TODO :...
2017-08-28 00:08:50 +02:00
etk::Vector<int16_t> data;
2015-01-25 22:17:06 +01:00
/*
data.resize(_nbChunk*m_map.size(), 0);
m_mutex.lock();
int32_t nbChunkBuffer = m_circularBuffer.size() / m_map.size();
m_mutex.unlock();
while (nbChunkBuffer < _nbChunk) {
2017-09-14 00:59:21 +02:00
ethread::sleepMilliSeconds((1));
2015-01-25 22:17:06 +01:00
nbChunkBuffer = m_circularBuffer.size() / m_map.size();
}
m_mutex.lock();
for (size_t iii = 0; iii<data.size(); ++iii) {
data[iii] = m_circularBuffer[iii];
}
m_circularBuffer.erase(m_circularBuffer.begin(), m_circularBuffer.begin()+data.size());
m_mutex.unlock();
*/
return data;
}
2015-01-27 21:01:52 +01:00
#endif
2015-01-25 22:17:06 +01:00
2015-04-11 09:38:30 +02:00
void audio::river::Interface::read(void* _value, size_t _nbChunk) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-02-09 21:44:32 +01:00
m_process.updateInterAlgo();
2015-01-25 22:17:06 +01:00
// TODO :...
}
2015-04-11 09:38:30 +02:00
size_t audio::river::Interface::size() const {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-01-25 22:17:06 +01:00
// TODO :...
return 0;
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::setBufferSize(size_t _nbChunk) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
algo->setBufferSize(_nbChunk);
return;
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
algo->setBufferSize(_nbChunk);
2015-01-25 22:17:06 +01:00
}
2017-09-26 15:57:44 +02:00
void audio::river::Interface::setBufferSize(const echrono::microseconds& _time) {
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
algo->setBufferSize(_time);
return;
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
algo->setBufferSize(_time);
}
2015-04-11 09:38:30 +02:00
size_t audio::river::Interface::getBufferSize() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferSize();
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferSize();
}
2017-09-26 15:57:44 +02:00
echrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
2017-09-26 15:57:44 +02:00
return echrono::microseconds(0);
}
return algo->getBufferSizeMicrosecond();
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
2017-09-26 15:57:44 +02:00
return echrono::microseconds(0);
}
return algo->getBufferSizeMicrosecond();
}
2015-04-11 09:38:30 +02:00
size_t audio::river::Interface::getBufferFillSize() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferFillSize();
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferFillSize();
2015-01-25 22:17:06 +01:00
}
2017-09-26 15:57:44 +02:00
echrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
ethread::RecursiveLock lock(m_mutex);
if (m_node->isInput() == true) {
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
2017-09-26 15:57:44 +02:00
return echrono::microseconds(0);
}
return algo->getBufferFillSizeMicrosecond();
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
2018-06-19 22:13:48 +02:00
if (algo == null) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
2017-09-26 15:57:44 +02:00
return echrono::microseconds(0);
}
return algo->getBufferFillSizeMicrosecond();
}
2015-04-11 09:38:30 +02:00
void audio::river::Interface::clearInternalBuffer() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-02-09 21:44:32 +01:00
m_process.updateInterAlgo();
2015-01-25 22:17:06 +01:00
// TODO :...
}
2015-04-13 21:49:48 +02:00
audio::Time audio::river::Interface::getCurrentTime() const {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
2015-01-25 22:17:06 +01:00
// TODO :...
2015-04-13 21:49:48 +02:00
return audio::Time();
return audio::Time::now();
2015-01-25 22:17:06 +01:00
}
2017-08-28 00:08:50 +02:00
void audio::river::Interface::addVolumeGroup(const etk::String& _name) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lock(m_mutex);
RIVER_DEBUG("addVolumeGroup(" << _name << ")");
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
2018-06-19 22:13:48 +02:00
if (algo == null) {
2015-03-05 22:14:07 +01:00
m_process.removeAlgoDynamic();
// add all time the volume stage :
2015-04-11 09:38:30 +02:00
algo = audio::drain::Volume::create();
2015-03-05 22:14:07 +01:00
algo->setName("volume");
if (m_node->isInput() == true) {
m_process.pushFront(algo);
} else {
m_process.pushBack(algo);
}
}
if (_name == "FLOW") {
// Local volume name
2016-07-19 21:43:58 +02:00
algo->addVolumeStage(ememory::makeShared<audio::drain::VolumeElement>(_name));
} else {
// get manager unique instance:
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
algo->addVolumeStage(mng->getVolumeGroup(_name));
}
}
2015-01-25 22:17:06 +01:00
2015-04-13 21:49:48 +02:00
void audio::river::Interface::systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lockProcess(m_mutex);
void * tmpData = const_cast<void*>(_data);
m_process.push(_time, tmpData, _nbChunk);
2015-01-25 22:17:06 +01:00
}
2015-04-13 21:49:48 +02:00
void audio::river::Interface::systemNeedOutputData(audio::Time _time, void* _data, size_t _nbChunk, size_t _chunkSize) {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lockProcess(m_mutex);
2015-03-04 22:15:35 +01:00
//RIVER_INFO("time : " << _time);
2015-02-09 21:44:32 +01:00
m_process.pull(_time, _data, _nbChunk, _chunkSize);
2015-01-25 22:17:06 +01:00
}
2015-01-30 21:44:36 +01:00
2015-04-11 09:38:30 +02:00
void audio::river::Interface::systemVolumeChange() {
2017-09-26 15:57:44 +02:00
ethread::RecursiveLock lockProcess(m_mutex);
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
2018-06-19 22:13:48 +02:00
if (algo == null) {
2015-02-04 21:08:06 +01:00
return;
}
algo->volumeChange();
2015-02-19 22:00:21 +01:00
}
2018-10-23 22:19:32 +02:00
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second, bool _isLink=true) {
2015-02-19 22:00:21 +01:00
if (_op == "->") {
2015-03-04 22:15:35 +01:00
if (_isLink) {
2018-10-23 22:19:32 +02:00
*_io << " " << _first << " -> " << _second << ";\n";
2015-03-04 22:15:35 +01:00
} else {
2018-10-23 22:19:32 +02:00
*_io << " " << _first << " -> " << _second << " [style=dashed];\n";
2015-03-04 22:15:35 +01:00
}
2015-02-19 22:00:21 +01:00
} else if (_op == "<-") {
2018-10-23 22:19:32 +02:00
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
2015-03-04 22:15:35 +01:00
if (_isLink) {
2018-10-23 22:19:32 +02:00
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
2015-03-04 22:15:35 +01:00
} else {
2018-10-23 22:19:32 +02:00
*_io << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
2015-03-04 22:15:35 +01:00
}
2015-02-19 22:00:21 +01:00
}
}
2017-08-28 00:08:50 +02:00
etk::String audio::river::Interface::getDotNodeName() const {
2015-04-11 09:38:30 +02:00
if (m_mode == audio::river::modeInterface_input) {
2017-08-28 00:08:50 +02:00
return "API_" + etk::toString(m_uid) + "_input";
2015-04-11 09:38:30 +02:00
} else if (m_mode == audio::river::modeInterface_feedback) {
2017-08-28 00:08:50 +02:00
return "API_" + etk::toString(m_uid) + "_feedback";
2015-04-11 09:38:30 +02:00
} else if (m_mode == audio::river::modeInterface_output) {
2017-08-28 00:08:50 +02:00
return "API_" + etk::toString(m_uid) + "_output";
2015-03-05 21:28:39 +01:00
}
return "error";
}
2018-10-23 22:19:32 +02:00
void audio::river::Interface::generateDot(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _nameIO, bool _isLink) {
*_io << " subgraph clusterInterface_" << m_uid << " {\n";
*_io << " color=orange;\n";
*_io << " label=\"[" << m_uid << "] Interface : " << m_name << "\";\n";
2017-08-28 00:08:50 +02:00
etk::String nameIn;
etk::String nameOut;
2015-04-11 09:38:30 +02:00
if ( m_mode == audio::river::modeInterface_input
|| m_mode == audio::river::modeInterface_feedback) {
2018-10-23 22:19:32 +02:00
m_process.generateDot(_io, 3, 10000+m_uid, nameIn, nameOut, false);
2015-03-05 22:14:07 +01:00
} else {
2018-10-23 22:19:32 +02:00
m_process.generateDot(_io, 3, 10000+m_uid, nameOut, nameIn, true);
2015-03-05 22:14:07 +01:00
}
2015-02-19 22:00:21 +01:00
2015-04-11 09:38:30 +02:00
if ( m_mode == audio::river::modeInterface_input
|| m_mode == audio::river::modeInterface_feedback) {
2018-10-23 22:19:32 +02:00
link(_io, _nameIO, "->", nameIn, _isLink);
2015-02-19 22:00:21 +01:00
} else {
2018-10-23 22:19:32 +02:00
link(_io, _nameIO, "<-", nameOut, _isLink);
2015-02-19 22:00:21 +01:00
}
2018-10-23 22:19:32 +02:00
*_io << " node [shape=Mdiamond];\n";
2015-04-11 09:38:30 +02:00
if (m_mode == audio::river::modeInterface_input) {
2018-10-23 22:19:32 +02:00
*_io << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
link(_io, nameOut, "->", getDotNodeName());
2015-04-11 09:38:30 +02:00
} else if (m_mode == audio::river::modeInterface_feedback) {
2018-10-23 22:19:32 +02:00
*_io << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
link(_io, nameOut, "->", getDotNodeName());
2015-04-11 09:38:30 +02:00
} else if (m_mode == audio::river::modeInterface_output) {
2018-10-23 22:19:32 +02:00
*_io << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
link(_io, nameIn, "<-", getDotNodeName());
2015-02-19 22:00:21 +01:00
}
2018-10-23 22:19:32 +02:00
*_io << " }\n \n";
2015-02-19 22:00:21 +01:00
}