[DEV] update drain pipeline and add process output
This commit is contained in:
parent
8ee3cc7544
commit
8896c0b5de
@ -25,5 +25,33 @@
|
|||||||
type:"int16",
|
type:"int16",
|
||||||
nb-chunk:1024,
|
nb-chunk:1024,
|
||||||
volume-name:"MASTER"
|
volume-name:"MASTER"
|
||||||
|
},
|
||||||
|
speaker-pulse:{
|
||||||
|
io:"output",
|
||||||
|
map-on:{
|
||||||
|
interface:"pulse",
|
||||||
|
name:"default",
|
||||||
|
},
|
||||||
|
frequency:48000,
|
||||||
|
channel-map:[
|
||||||
|
"front-left", "front-right",
|
||||||
|
],
|
||||||
|
type:"int16",
|
||||||
|
nb-chunk:1024,
|
||||||
|
volume-name:"MASTER"
|
||||||
|
},
|
||||||
|
speaker-jack:{
|
||||||
|
io:"output",
|
||||||
|
map-on:{
|
||||||
|
interface:"jack",
|
||||||
|
name:"default",
|
||||||
|
},
|
||||||
|
frequency:48000,
|
||||||
|
channel-map:[
|
||||||
|
"front-left", "front-right",
|
||||||
|
],
|
||||||
|
type:"float",
|
||||||
|
nb-chunk:1024,
|
||||||
|
volume-name:"MASTER"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,9 +42,10 @@ bool river::Interface::init(const std::string& _name,
|
|||||||
m_node->registerAsRemote(shared_from_this());
|
m_node->registerAsRemote(shared_from_this());
|
||||||
// Create convertion interface
|
// Create convertion interface
|
||||||
if (m_node->isInput() == true) {
|
if (m_node->isInput() == true) {
|
||||||
|
m_process->setInputConfig(m_node->getInterfaceFormat());
|
||||||
// add all time the volume stage :
|
// add all time the volume stage :
|
||||||
std::shared_ptr<drain::Volume> algo = drain::Volume::create();
|
std::shared_ptr<drain::Volume> algo = drain::Volume::create();
|
||||||
algo->setInputFormat(m_node->getInterfaceFormat());
|
//algo->setInputFormat(m_node->getInterfaceFormat());
|
||||||
algo->setName("volume");
|
algo->setName("volume");
|
||||||
m_process->pushBack(algo);
|
m_process->pushBack(algo);
|
||||||
RIVER_INFO("add basic volume stage (1)");
|
RIVER_INFO("add basic volume stage (1)");
|
||||||
@ -53,10 +54,12 @@ bool river::Interface::init(const std::string& _name,
|
|||||||
RIVER_INFO(" add volume for node");
|
RIVER_INFO(" add volume for node");
|
||||||
algo->addVolumeStage(tmpVolume);
|
algo->addVolumeStage(tmpVolume);
|
||||||
}
|
}
|
||||||
|
m_process->setOutputConfig(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
} else {
|
} else {
|
||||||
|
m_process->setInputConfig(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
// add all time the volume stage :
|
// add all time the volume stage :
|
||||||
std::shared_ptr<drain::Volume> algo = drain::Volume::create();
|
std::shared_ptr<drain::Volume> algo = drain::Volume::create();
|
||||||
algo->setOutputFormat(m_node->getInterfaceFormat());
|
//algo->setOutputFormat(m_node->getInterfaceFormat());
|
||||||
algo->setName("volume");
|
algo->setName("volume");
|
||||||
m_process->pushBack(algo);
|
m_process->pushBack(algo);
|
||||||
RIVER_INFO("add basic volume stage (2)");
|
RIVER_INFO("add basic volume stage (2)");
|
||||||
@ -65,6 +68,7 @@ bool river::Interface::init(const std::string& _name,
|
|||||||
RIVER_INFO(" add volume for node");
|
RIVER_INFO(" add volume for node");
|
||||||
algo->addVolumeStage(tmpVolume);
|
algo->addVolumeStage(tmpVolume);
|
||||||
}
|
}
|
||||||
|
m_process->setOutputConfig(m_node->getInterfaceFormat());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -100,14 +104,12 @@ void river::Interface::setReadwrite() {
|
|||||||
if (m_node->isInput() == true) {
|
if (m_node->isInput() == true) {
|
||||||
m_process->removeIfLast<drain::EndPoint>();
|
m_process->removeIfLast<drain::EndPoint>();
|
||||||
std::shared_ptr<drain::EndPointRead> algo = drain::EndPointRead::create();
|
std::shared_ptr<drain::EndPointRead> algo = drain::EndPointRead::create();
|
||||||
///algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
//algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
|
||||||
m_process->pushBack(algo);
|
m_process->pushBack(algo);
|
||||||
} else {
|
} else {
|
||||||
m_process->removeIfFirst<drain::EndPoint>();
|
m_process->removeIfFirst<drain::EndPoint>();
|
||||||
std::shared_ptr<drain::EndPointWrite> algo = drain::EndPointWrite::create();
|
std::shared_ptr<drain::EndPointWrite> algo = drain::EndPointWrite::create();
|
||||||
algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
//algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
//algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
|
||||||
m_process->pushFront(algo);
|
m_process->pushFront(algo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,8 +120,7 @@ void river::Interface::setOutputCallback(size_t _chunkSize, drain::needDataFunct
|
|||||||
m_process->removeIfFirst<drain::EndPoint>();
|
m_process->removeIfFirst<drain::EndPoint>();
|
||||||
std::shared_ptr<drain::Algo> algo = drain::EndPointCallback::create(_function);
|
std::shared_ptr<drain::Algo> algo = drain::EndPointCallback::create(_function);
|
||||||
RIVER_INFO("set property: " << m_map << " " << m_format << " " << m_freq);
|
RIVER_INFO("set property: " << m_map << " " << m_format << " " << m_freq);
|
||||||
algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
//algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
//algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
|
||||||
m_process->pushFront(algo);
|
m_process->pushFront(algo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +129,7 @@ void river::Interface::setInputCallback(size_t _chunkSize, drain::haveNewDataFun
|
|||||||
m_process->removeAlgoDynamic();
|
m_process->removeAlgoDynamic();
|
||||||
m_process->removeIfLast<drain::EndPoint>();
|
m_process->removeIfLast<drain::EndPoint>();
|
||||||
std::shared_ptr<drain::Algo> algo = drain::EndPointCallback::create(_function);
|
std::shared_ptr<drain::Algo> algo = drain::EndPointCallback::create(_function);
|
||||||
//algo->setInputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
//algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
||||||
algo->setOutputFormat(drain::IOFormatInterface(m_map, m_format, m_freq));
|
|
||||||
m_process->pushBack(algo);
|
m_process->pushBack(algo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,18 +36,17 @@ int32_t river::io::Node::rtAudioCallback(void* _outputBuffer,
|
|||||||
if (_outputBuffer != nullptr) {
|
if (_outputBuffer != nullptr) {
|
||||||
RIVER_VERBOSE("data Output");
|
RIVER_VERBOSE("data Output");
|
||||||
std::vector<int32_t> output;
|
std::vector<int32_t> output;
|
||||||
output.resize(_nBufferFrames*m_interfaceFormat.getMap().size(), 0);
|
output.resize(_nBufferFrames*m_process.getInputConfig().getMap().size(), 0);
|
||||||
const int32_t* outputTmp = nullptr;
|
const int32_t* outputTmp = nullptr;
|
||||||
std::vector<uint8_t> outputTmp2;
|
std::vector<uint8_t> outputTmp2;
|
||||||
outputTmp2.resize(sizeof(int32_t)*m_interfaceFormat.getMap().size()*_nBufferFrames, 0);
|
outputTmp2.resize(sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nBufferFrames, 0);
|
||||||
for (auto &it : m_list) {
|
for (auto &it : m_list) {
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
// clear datas ...
|
// clear datas ...
|
||||||
memset(&outputTmp2[0], 0, sizeof(int32_t)*m_interfaceFormat.getMap().size()*_nBufferFrames);
|
memset(&outputTmp2[0], 0, sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nBufferFrames);
|
||||||
RIVER_VERBOSE(" IO : " /* << std::distance(m_list.begin(), it)*/ << "/" << m_list.size() << " name="<< it->getName());
|
RIVER_VERBOSE(" IO : " /* << std::distance(m_list.begin(), it)*/ << "/" << m_list.size() << " name="<< it->getName());
|
||||||
it->systemNeedOutputData(ttime, &outputTmp2[0], _nBufferFrames, sizeof(int32_t)*m_interfaceFormat.getMap().size());
|
it->systemNeedOutputData(ttime, &outputTmp2[0], _nBufferFrames, sizeof(int32_t)*m_process.getInputConfig().getMap().size());
|
||||||
outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]);
|
outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]);
|
||||||
//it->systemNeedOutputData(ttime, _outputBuffer, _nBufferFrames, sizeof(int16_t)*m_map.size());
|
|
||||||
// Add data to the output tmp buffer :
|
// Add data to the output tmp buffer :
|
||||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||||
output[kkk] += outputTmp[kkk];
|
output[kkk] += outputTmp[kkk];
|
||||||
@ -55,10 +54,8 @@ int32_t river::io::Node::rtAudioCallback(void* _outputBuffer,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int16_t* outputBuffer = static_cast<int16_t*>(_outputBuffer);
|
m_process.processIn(&outputTmp2[0], _nBufferFrames, _outputBuffer, _nBufferFrames);
|
||||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
// TODO : Call feedback ...
|
||||||
*outputBuffer++ = static_cast<int16_t>(std::min(std::max(INT16_MIN, output[kkk]), INT16_MAX));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_inputBuffer != nullptr) {
|
if (_inputBuffer != nullptr) {
|
||||||
RIVER_INFO("data Input");
|
RIVER_INFO("data Input");
|
||||||
@ -85,6 +82,8 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
RIVER_INFO("-----------------------------------------------------------------");
|
RIVER_INFO("-----------------------------------------------------------------");
|
||||||
RIVER_INFO("-- CREATE NODE --");
|
RIVER_INFO("-- CREATE NODE --");
|
||||||
RIVER_INFO("-----------------------------------------------------------------");
|
RIVER_INFO("-----------------------------------------------------------------");
|
||||||
|
drain::IOFormatInterface interfaceFormat;
|
||||||
|
drain::IOFormatInterface hardwareFormat;
|
||||||
/**
|
/**
|
||||||
io:"input", # input or output
|
io:"input", # input or output
|
||||||
map-on:{ # select hardware interface and name
|
map-on:{ # select hardware interface and name
|
||||||
@ -120,12 +119,7 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
m_volume = river::io::Manager::getInstance()->getVolumeGroup(volumeName);
|
m_volume = river::io::Manager::getInstance()->getVolumeGroup(volumeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::format formatType = audio::format_int16;
|
enum audio::format formatType = audio::getFormatFromString(type);
|
||||||
if (type == "int16") {
|
|
||||||
formatType = audio::format_int16;
|
|
||||||
} else {
|
|
||||||
RIVER_WARNING("not managed type : '" << type << "'");
|
|
||||||
}
|
|
||||||
// TODO : MAP ...
|
// TODO : MAP ...
|
||||||
|
|
||||||
// intanciate specific API ...
|
// intanciate specific API ...
|
||||||
@ -140,22 +134,22 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
map.push_back(audio::channel_frontLeft);
|
map.push_back(audio::channel_frontLeft);
|
||||||
map.push_back(audio::channel_frontRight);
|
map.push_back(audio::channel_frontRight);
|
||||||
|
|
||||||
m_hardwareFormat.set(map, formatType, frequency);
|
hardwareFormat.set(map, formatType, frequency);
|
||||||
// TODO : Better view of interface type float -> float, int16 -> int16/int32, ...
|
// TODO : Better view of interface type float -> float, int16 -> int16/int32, ...
|
||||||
if (m_isInput == true) {
|
if (m_isInput == true) {
|
||||||
// for input we just transfert audio with no transformation
|
// for input we just transfert audio with no transformation
|
||||||
m_interfaceFormat.set(map, audio::format_int16, frequency);
|
interfaceFormat.set(map, audio::format_int16, frequency);
|
||||||
} else {
|
} else {
|
||||||
// for output we will do a mix ...
|
// for output we will do a mix ...
|
||||||
m_interfaceFormat.set(map, audio::format_int16_on_int32, frequency);
|
interfaceFormat.set(map, audio::format_int16_on_int32, frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
// search device ID :
|
// search device ID :
|
||||||
RIVER_INFO("Open :");
|
RIVER_INFO("Open :");
|
||||||
RIVER_INFO(" m_streamName=" << streamName);
|
RIVER_INFO(" m_streamName=" << streamName);
|
||||||
RIVER_INFO(" m_freq=" << m_hardwareFormat.getFrequency());
|
RIVER_INFO(" m_freq=" << hardwareFormat.getFrequency());
|
||||||
RIVER_INFO(" m_map=" << m_hardwareFormat.getMap());
|
RIVER_INFO(" m_map=" << hardwareFormat.getMap());
|
||||||
RIVER_INFO(" m_format=" << m_hardwareFormat.getFormat());
|
RIVER_INFO(" m_format=" << hardwareFormat.getFormat());
|
||||||
RIVER_INFO(" m_isInput=" << m_isInput);
|
RIVER_INFO(" m_isInput=" << m_isInput);
|
||||||
int32_t deviceId = 0;
|
int32_t deviceId = 0;
|
||||||
RIVER_INFO("Device list:");
|
RIVER_INFO("Device list:");
|
||||||
@ -179,13 +173,16 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
RIVER_INFO(" duplexChannels=" << m_info.duplexChannels);
|
RIVER_INFO(" duplexChannels=" << m_info.duplexChannels);
|
||||||
RIVER_INFO(" isDefaultOutput=" << m_info.isDefaultOutput);
|
RIVER_INFO(" isDefaultOutput=" << m_info.isDefaultOutput);
|
||||||
RIVER_INFO(" isDefaultInput=" << m_info.isDefaultInput);
|
RIVER_INFO(" isDefaultInput=" << m_info.isDefaultInput);
|
||||||
//std::string rrate;
|
RIVER_INFO(" rates=" << m_info.sampleRates);
|
||||||
std::stringstream rrate;
|
|
||||||
for (int32_t jjj=0; jjj<m_info.sampleRates.size(); ++jjj) {
|
|
||||||
rrate << m_info.sampleRates[jjj] << ";";
|
|
||||||
}
|
|
||||||
RIVER_INFO(" rates=" << rrate.str());
|
|
||||||
RIVER_INFO(" native Format: " << m_info.nativeFormats);
|
RIVER_INFO(" native Format: " << m_info.nativeFormats);
|
||||||
|
if (etk::isIn(hardwareFormat.getFormat(), m_info.nativeFormats) == false) {
|
||||||
|
RIVER_CRITICAL("Can not manage input transforamtion: " << hardwareFormat.getFormat() << " not in " << m_info.nativeFormats);
|
||||||
|
// TODO : Manage this
|
||||||
|
}
|
||||||
|
if (etk::isIn(hardwareFormat.getFrequency(), m_info.sampleRates) == false) {
|
||||||
|
RIVER_CRITICAL("Can not manage input transforamtion:" << hardwareFormat.getFrequency() << " not in " << m_info.sampleRates);
|
||||||
|
// TODO : Manage this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// open Audio device:
|
// open Audio device:
|
||||||
@ -204,7 +201,7 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
enum airtaudio::error err = airtaudio::error_none;
|
enum airtaudio::error err = airtaudio::error_none;
|
||||||
if (m_isInput == true) {
|
if (m_isInput == true) {
|
||||||
err = m_adac.openStream(nullptr, ¶ms,
|
err = m_adac.openStream(nullptr, ¶ms,
|
||||||
audio::format_int16, m_hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
|
audio::format_int16, hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
|
||||||
std::bind(&river::io::Node::rtAudioCallback,
|
std::bind(&river::io::Node::rtAudioCallback,
|
||||||
this,
|
this,
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
@ -215,7 +212,7 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
err = m_adac.openStream(¶ms, nullptr,
|
err = m_adac.openStream(¶ms, nullptr,
|
||||||
audio::format_int16, m_hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
|
audio::format_int16, hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
|
||||||
std::bind(&river::io::Node::rtAudioCallback,
|
std::bind(&river::io::Node::rtAudioCallback,
|
||||||
this,
|
this,
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
@ -228,6 +225,13 @@ river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejso
|
|||||||
if (err != airtaudio::error_none) {
|
if (err != airtaudio::error_none) {
|
||||||
RIVER_ERROR("Create stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not create stream " << err);
|
RIVER_ERROR("Create stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not create stream " << err);
|
||||||
}
|
}
|
||||||
|
if (m_isInput == true) {
|
||||||
|
m_process.setInputConfig(hardwareFormat);
|
||||||
|
m_process.setOutputConfig(interfaceFormat);
|
||||||
|
} else {
|
||||||
|
m_process.setOutputConfig(hardwareFormat);
|
||||||
|
m_process.setInputConfig(interfaceFormat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
river::io::Node::~Node() {
|
river::io::Node::~Node() {
|
||||||
|
@ -65,13 +65,15 @@ namespace river {
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
drain::IOFormatInterface m_interfaceFormat;
|
drain::Process m_process;
|
||||||
public:
|
public:
|
||||||
const drain::IOFormatInterface& getInterfaceFormat() {
|
const drain::IOFormatInterface& getInterfaceFormat() {
|
||||||
return m_interfaceFormat;
|
if (m_isInput == true) {
|
||||||
|
return m_process.getOutputConfig();
|
||||||
|
} else {
|
||||||
|
return m_process.getInputConfig();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
drain::IOFormatInterface m_hardwareFormat;
|
|
||||||
private:
|
private:
|
||||||
bool m_isInput;
|
bool m_isInput;
|
||||||
public:
|
public:
|
||||||
|
@ -156,7 +156,7 @@ class testOutCallback {
|
|||||||
std::shared_ptr<river::Interface> m_interface;
|
std::shared_ptr<river::Interface> m_interface;
|
||||||
double m_phase;
|
double m_phase;
|
||||||
public:
|
public:
|
||||||
testOutCallback(std::shared_ptr<river::Manager> _manager) :
|
testOutCallback(std::shared_ptr<river::Manager> _manager, const std::string& _io="speaker") :
|
||||||
m_manager(_manager),
|
m_manager(_manager),
|
||||||
m_phase(0) {
|
m_phase(0) {
|
||||||
//Set stereo output:
|
//Set stereo output:
|
||||||
@ -166,7 +166,7 @@ class testOutCallback {
|
|||||||
m_interface = m_manager->createOutput(48000,
|
m_interface = m_manager->createOutput(48000,
|
||||||
channelMap,
|
channelMap,
|
||||||
audio::format_int16,
|
audio::format_int16,
|
||||||
"speaker",
|
_io,
|
||||||
"WriteModeCallback");
|
"WriteModeCallback");
|
||||||
// set callback mode ...
|
// set callback mode ...
|
||||||
m_interface->setOutputCallback(1024,
|
m_interface->setOutputCallback(1024,
|
||||||
@ -211,7 +211,29 @@ TEST(TestALL, testOutputCallBack) {
|
|||||||
manager = river::Manager::create("testApplication");
|
manager = river::Manager::create("testApplication");
|
||||||
|
|
||||||
APPL_INFO("test output (callback mode)");
|
APPL_INFO("test output (callback mode)");
|
||||||
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager);
|
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker");
|
||||||
|
process->run();
|
||||||
|
process.reset();
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestALL, testOutputCallBackPulse) {
|
||||||
|
std::shared_ptr<river::Manager> manager;
|
||||||
|
manager = river::Manager::create("testApplication");
|
||||||
|
|
||||||
|
APPL_INFO("test output (callback mode)");
|
||||||
|
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker-pulse");
|
||||||
|
process->run();
|
||||||
|
process.reset();
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestALL, testOutputCallBackJack) {
|
||||||
|
std::shared_ptr<river::Manager> manager;
|
||||||
|
manager = river::Manager::create("testApplication");
|
||||||
|
|
||||||
|
APPL_INFO("test output (callback mode)");
|
||||||
|
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker-jack");
|
||||||
process->run();
|
process->run();
|
||||||
process.reset();
|
process.reset();
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user