[DEV] update new ETK

This commit is contained in:
Edouard DUPIN 2017-09-26 15:57:44 +02:00
parent 4bc3ff2f1a
commit 309b63254f
26 changed files with 139 additions and 164 deletions

View File

@ -8,10 +8,7 @@
//#include <etk/types.hpp> //#include <etk/types.hpp>
#include <audio/orchestra/Interface.hpp> #include <audio/orchestra/Interface.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <iostream> #include <etk/types.hpp>
#include <cstdlib>
#include <cstring>
#include <climits>
// Static variable definitions. // Static variable definitions.
const etk::Vector<uint32_t>& audio::orchestra::genericSampleRate() { const etk::Vector<uint32_t>& audio::orchestra::genericSampleRate() {
@ -55,7 +52,7 @@ audio::orchestra::Api::~Api() {
enum audio::orchestra::error audio::orchestra::Api::startStream() { enum audio::orchestra::error audio::orchestra::Api::startStream() {
ATA_VERBOSE("Start Stream"); ATA_VERBOSE("Start Stream");
m_startTime = audio::Time::now(); m_startTime = audio::Time::now();
m_duration = std::chrono::microseconds(0); m_duration = echrono::microseconds(0);
return audio::orchestra::error_none; return audio::orchestra::error_none;
} }

View File

@ -6,7 +6,7 @@
*/ */
#pragma once #pragma once
#include <sstream> #include <etk/Stream.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <audio/orchestra/type.hpp> #include <audio/orchestra/type.hpp>
#include <audio/orchestra/state.hpp> #include <audio/orchestra/state.hpp>
@ -33,11 +33,11 @@ namespace audio {
* @param _status List of error that occured in the laps of time. * @param _status List of error that occured in the laps of time.
*/ */
typedef etk::Function<int32_t (const void* _inputBuffer, typedef etk::Function<int32_t (const void* _inputBuffer,
const audio::Time& _timeInput, const audio::Time& _timeInput,
void* _outputBuffer, void* _outputBuffer,
const audio::Time& _timeOutput, const audio::Time& _timeOutput,
uint32_t _nbChunk, uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status)> AirTAudioCallback; const etk::Vector<audio::orchestra::status>& _status)> AirTAudioCallback;
// A protected structure used for buffer conversion. // A protected structure used for buffer conversion.
class ConvertInfo { class ConvertInfo {
public: public:

View File

@ -9,7 +9,6 @@
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <audio/orchestra/DeviceInfo.hpp> #include <audio/orchestra/DeviceInfo.hpp>
#include <etk/stdTools.hpp> #include <etk/stdTools.hpp>
#include <iostream>
void audio::orchestra::DeviceInfo::display(int32_t _tabNumber) const { void audio::orchestra::DeviceInfo::display(int32_t _tabNumber) const {
etk::String space; etk::String space;

View File

@ -8,7 +8,6 @@
//#include <etk/types.hpp> //#include <etk/types.hpp>
#include <audio/orchestra/Interface.hpp> #include <audio/orchestra/Interface.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <iostream>
#include <audio/orchestra/api/Alsa.hpp> #include <audio/orchestra/api/Alsa.hpp>
#include <audio/orchestra/api/Android.hpp> #include <audio/orchestra/api/Android.hpp>
#include <audio/orchestra/api/Asio.hpp> #include <audio/orchestra/api/Asio.hpp>

View File

@ -8,6 +8,7 @@
#include <etk/String.hpp> #include <etk/String.hpp>
#include <etk/Vector.hpp> #include <etk/Vector.hpp>
#include <etk/Pair.hpp>
#include <audio/orchestra/base.hpp> #include <audio/orchestra/base.hpp>
#include <audio/orchestra/CallbackInfo.hpp> #include <audio/orchestra/CallbackInfo.hpp>
#include <audio/orchestra/Api.hpp> #include <audio/orchestra/Api.hpp>
@ -183,12 +184,12 @@ namespace audio {
* when an error has occured. * when an error has occured.
*/ */
enum audio::orchestra::error openStream(audio::orchestra::StreamParameters *_outputParameters, enum audio::orchestra::error openStream(audio::orchestra::StreamParameters *_outputParameters,
audio::orchestra::StreamParameters *_inputParameters, audio::orchestra::StreamParameters *_inputParameters,
enum audio::format _format, enum audio::format _format,
uint32_t _sampleRate, uint32_t _sampleRate,
uint32_t* _bufferFrames, uint32_t* _bufferFrames,
audio::orchestra::AirTAudioCallback _callback, audio::orchestra::AirTAudioCallback _callback,
const audio::orchestra::StreamOptions& _options = audio::orchestra::StreamOptions()); const audio::orchestra::StreamOptions& _options = audio::orchestra::StreamOptions());
/** /**
* @brief A function that closes a stream and frees any associated stream memory. * @brief A function that closes a stream and frees any associated stream memory.

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <audio/orchestra/Flags.hpp> #include <audio/orchestra/Flags.hpp>
#include <etk/String.hpp>
namespace audio { namespace audio {
namespace orchestra { namespace orchestra {

View File

@ -14,19 +14,19 @@
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <etk/stdTools.hpp> #include <etk/stdTools.hpp>
#include <ethread/tools.hpp> #include <ethread/tools.hpp>
#include <climits>
#include <audio/orchestra/api/Alsa.hpp> #include <audio/orchestra/api/Alsa.hpp>
extern "C" { extern "C" {
#include <sched.h> #include <sched.h>
#include <getopt.h> #include <getopt.h>
#include <sys/time.h> #include <sys/time.h>
#include <poll.h> #include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
} }
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Alsa::create() { ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Alsa::create() {
return ememory::SharedPtr<audio::orchestra::api::Alsa>(new audio::orchestra::api::Alsa()); return ememory::SharedPtr<audio::orchestra::api::Alsa>(new audio::orchestra::api::Alsa());
@ -39,7 +39,7 @@ namespace audio {
public: public:
snd_pcm_t *handle; snd_pcm_t *handle;
bool xrun[2]; bool xrun[2];
std::condition_variable runnable_cv; ethread::Semaphore m_semaphore;
bool runnable; bool runnable;
ethread::Thread* thread; ethread::Thread* thread;
bool threadRunning; bool threadRunning;
@ -194,11 +194,9 @@ bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const etk::String& _de
} }
// Test our discrete set of sample rate values. // Test our discrete set of sample rate values.
_info.sampleRates.clear(); _info.sampleRates.clear();
for (etk::Vector<uint32_t>::const_iterator it(audio::orchestra::genericSampleRate().begin()); for (auto &it: audio::orchestra::genericSampleRate()) {
it != audio::orchestra::genericSampleRate().end(); if (snd_pcm_hw_params_test_rate(phandle, params, it, 0) == 0) {
++it ) { _info.sampleRates.pushBack(it);
if (snd_pcm_hw_params_test_rate(phandle, params, *it, 0) == 0) {
_info.sampleRates.pushBack(*it);
} }
} }
if (_info.sampleRates.size() == 0) { if (_info.sampleRates.size() == 0) {
@ -803,7 +801,7 @@ bool audio::orchestra::api::Alsa::openName(const etk::String& _deviceName,
// Setup callback thread. // Setup callback thread.
m_private->threadRunning = true; m_private->threadRunning = true;
ATA_INFO("create thread ..."); ATA_INFO("create thread ...");
m_private->thread = new ethread::Thread(&audio::orchestra::api::Alsa::alsaCallbackEvent, this); m_private->thread = new ethread::Thread([=]() {callbackEvent();});
if (m_private->thread == nullptr) { if (m_private->thread == nullptr) {
m_private->threadRunning = false; m_private->threadRunning = false;
ATA_ERROR("creating callback thread!"); ATA_ERROR("creating callback thread!");
@ -836,9 +834,9 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::closeStream() {
m_mutex.lock(); m_mutex.lock();
if (m_state == audio::orchestra::state::stopped) { if (m_state == audio::orchestra::state::stopped) {
m_private->runnable = true; m_private->runnable = true;
m_private->runnable_cv.notify_one(); m_private->m_semaphore.post();
} }
m_mutex.unlock(); m_mutex.unLock();
if (m_private->thread != nullptr) { if (m_private->thread != nullptr) {
m_private->thread->join(); m_private->thread->join();
m_private->thread = nullptr; m_private->thread = nullptr;
@ -865,23 +863,29 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::closeStream() {
} }
enum audio::orchestra::error audio::orchestra::api::Alsa::startStream() { enum audio::orchestra::error audio::orchestra::api::Alsa::startStream() {
ATA_DEBUG("Start stream (DEGIN)");
// TODO : Check return ... // TODO : Check return ...
//audio::orchestra::Api::startStream(); //audio::orchestra::Api::startStream();
// This method calls snd_pcm_prepare if the device isn't already in that state. // This method calls snd_pcm_prepare if the device isn't already in that state.
if (verifyStream() != audio::orchestra::error_none) { if (verifyStream() != audio::orchestra::error_none) {
ATA_WARNING("the stream not prepared!");
return audio::orchestra::error_fail; return audio::orchestra::error_fail;
} }
if (m_state == audio::orchestra::state::running) { if (m_state == audio::orchestra::state::running) {
ATA_ERROR("the stream is already running!"); ATA_ERROR("the stream is already running!");
return audio::orchestra::error_warning; return audio::orchestra::error_warning;
} }
ATA_DEBUG("Lock");
ethread::UniqueLock lck(m_mutex); ethread::UniqueLock lck(m_mutex);
ATA_DEBUG("Lock (done)");
int32_t result = 0; int32_t result = 0;
snd_pcm_state_t state; snd_pcm_state_t state;
if (m_private->handle == nullptr) { if (m_private->handle == nullptr) {
ATA_ERROR("send nullptr to alsa ..."); ATA_ERROR("send nullptr to alsa ...");
} }
ATA_DEBUG("snd_pcm_state");
state = snd_pcm_state(m_private->handle); state = snd_pcm_state(m_private->handle);
ATA_DEBUG("snd_pcm_state (done)");
if (state != SND_PCM_STATE_PREPARED) { if (state != SND_PCM_STATE_PREPARED) {
ATA_ERROR("prepare stream"); ATA_ERROR("prepare stream");
result = snd_pcm_prepare(m_private->handle); result = snd_pcm_prepare(m_private->handle);
@ -893,10 +897,12 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::startStream() {
m_state = audio::orchestra::state::running; m_state = audio::orchestra::state::running;
unlock: unlock:
m_private->runnable = true; m_private->runnable = true;
m_private->runnable_cv.notify_one(); m_private->m_semaphore.post();
if (result >= 0) { if (result >= 0) {
ATA_DEBUG("Start stream (END2)");
return audio::orchestra::error_none; return audio::orchestra::error_none;
} }
ATA_DEBUG("Start stream (END)");
return audio::orchestra::error_systemError; return audio::orchestra::error_systemError;
} }
@ -950,12 +956,6 @@ unlock:
return audio::orchestra::error_systemError; return audio::orchestra::error_systemError;
} }
void audio::orchestra::api::Alsa::alsaCallbackEvent(void *_userData) {
audio::orchestra::api::Alsa* myClass = reinterpret_cast<audio::orchestra::api::Alsa*>(_userData);
myClass->callbackEvent();
}
/** /**
* @briefTransfer method - write and wait for room in buffer using poll * @briefTransfer method - write and wait for room in buffer using poll
*/ */
@ -979,9 +979,8 @@ static int32_t wait_for_poll(snd_pcm_t* _handle, struct pollfd* _ufds, unsigned
void audio::orchestra::api::Alsa::callbackEvent() { void audio::orchestra::api::Alsa::callbackEvent() {
// Lock while the system is not started ... // Lock while the system is not started ...
if (m_state == audio::orchestra::state::stopped) { if (m_state == audio::orchestra::state::stopped) {
ethread::UniqueLock lck(m_mutex);
while (!m_private->runnable) { while (!m_private->runnable) {
m_private->runnable_cv.wait(lck); m_private->m_semaphore.wait();
} }
if (m_state != audio::orchestra::state::running) { if (m_state != audio::orchestra::state::running) {
return; return;
@ -1055,7 +1054,7 @@ audio::Time audio::orchestra::api::Alsa::getStreamTime() {
ATA_VERBOSE("snd_pcm_status_get_htstamp : " << m_startTime); ATA_VERBOSE("snd_pcm_status_get_htstamp : " << m_startTime);
snd_pcm_sframes_t delay = snd_pcm_status_get_delay(status); snd_pcm_sframes_t delay = snd_pcm_status_get_delay(status);
audio::Duration timeDelay = audio::Duration(0, delay*1000000000LL/int64_t(m_sampleRate)); audio::Duration timeDelay = audio::Duration(0, delay*1000000000LL/int64_t(m_sampleRate));
ATA_VERBOSE("delay : " << timeDelay.count() << " ns"); ATA_VERBOSE("delay : " << timeDelay);
//return m_startTime + m_duration; //return m_startTime + m_duration;
if (m_mode == audio::orchestra::mode_output) { if (m_mode == audio::orchestra::mode_output) {
// output // output
@ -1201,7 +1200,7 @@ noInput:
audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate)); audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate));
audio::Duration timeProcess = stopCall - startCall; audio::Duration timeProcess = stopCall - startCall;
if (timeDelay <= timeProcess) { if (timeDelay <= timeProcess) {
ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay.count() << " < " << timeProcess.count() << " (process time) ns"); ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay << " < " << timeProcess << " (process time)");
} }
} }
if (doStopStream == 2) { if (doStopStream == 2) {
@ -1251,7 +1250,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleWrite() {
audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate)); audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate));
audio::Duration timeProcess = stopCall - startCall; audio::Duration timeProcess = stopCall - startCall;
if (timeDelay <= timeProcess) { if (timeDelay <= timeProcess) {
ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay.count() << " < " << timeProcess.count() << " (process time) ns"); ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay << " < " << timeProcess << " (process time)");
} }
} }
if (doStopStream == 2) { if (doStopStream == 2) {
@ -1357,7 +1356,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate)); audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate));
audio::Duration timeProcess = stopCall - startCall; audio::Duration timeProcess = stopCall - startCall;
if (timeDelay <= timeProcess) { if (timeDelay <= timeProcess) {
ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay.count() << " < " << timeProcess.count() << " (process time) ns"); ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay << " < " << timeProcess << " (process time)");
} }
} }
if (doStopStream == 2) { if (doStopStream == 2) {
@ -1557,7 +1556,7 @@ noInput:
audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate)); audio::Duration timeDelay(0, m_bufferSize*1000000000LL/int64_t(m_sampleRate));
audio::Duration timeProcess = stopCall - startCall; audio::Duration timeProcess = stopCall - startCall;
if (timeDelay <= timeProcess) { if (timeDelay <= timeProcess) {
ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay.count() << " < " << timeProcess.count() << " (process time) ns"); ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay << " < " << timeProcess << " (process time) ns");
} }
} }
if (doStopStream == 2) { if (doStopStream == 2) {

View File

@ -47,8 +47,6 @@ namespace audio {
void callbackEventOneCycleWrite(); void callbackEventOneCycleWrite();
void callbackEventOneCycleMMAPRead(); void callbackEventOneCycleMMAPRead();
void callbackEventOneCycleMMAPWrite(); void callbackEventOneCycleMMAPWrite();
private:
static void alsaCallbackEvent(void* _userData);
private: private:
ememory::SharedPtr<AlsaPrivate> m_private; ememory::SharedPtr<AlsaPrivate> m_private;
etk::Vector<audio::orchestra::DeviceInfo> m_devices; etk::Vector<audio::orchestra::DeviceInfo> m_devices;

View File

@ -13,7 +13,9 @@
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <audio/orchestra/api/AndroidNativeInterface.hpp> #include <audio/orchestra/api/AndroidNativeInterface.hpp>
#include <audio/orchestra/api/Android.hpp> #include <audio/orchestra/api/Android.hpp>
#include <climits> extern "C" {
#include <limits.h>
}
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Android::create() { ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Android::create() {
ATA_INFO("Create Android device ... "); ATA_INFO("Create Android device ... ");

View File

@ -4,8 +4,10 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <jni.h> extern "C" {
#include <pthread.h> #include <jni.h>
#include <pthread.h>
}
#include <ethread/Mutex.hpp> #include <ethread/Mutex.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <audio/orchestra/error.hpp> #include <audio/orchestra/error.hpp>

View File

@ -32,12 +32,13 @@ ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Asio::create()
// on information found in // on information found in
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
#include "asiosys.h" extern "C" {
#include "asio.h" #include "asiosys.h"
#include "iasiothiscallresolver.h" #include "asio.h"
#include "asiodrivers.h" #include "iasiothiscallresolver.h"
#include <cmath> #include "asiodrivers.h"
#include <math.h>
}
static AsioDrivers drivers; static AsioDrivers drivers;
static ASIOCallbacks asioCallbacks; static ASIOCallbacks asioCallbacks;
static ASIODriverInfo driverInfo; static ASIODriverInfo driverInfo;

View File

@ -37,7 +37,7 @@ namespace audio {
uint32_t nStreams[2]; // number of streams to use uint32_t nStreams[2]; // number of streams to use
bool xrun[2]; bool xrun[2];
char *deviceBuffer; char *deviceBuffer;
std::condition_variable condition; ethread::Semaphore m_semaphore;
int32_t drainCounter; // Tracks callback counts when draining int32_t drainCounter; // Tracks callback counts when draining
bool internalDrain; // Indicates if stop is initiated from callback or not. bool internalDrain; // Indicates if stop is initiated from callback or not.
CorePrivate() : CorePrivate() :
@ -680,11 +680,11 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream physical format for device (" << _device << ")."); ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream physical format for device (" << _device << ").");
return false; return false;
} }
//std::cout << "Current physical stream format:" << std::endl; //ATA_DEBUG("Current physical stream format:");
//std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl; //ATA_DEBUG(" mBitsPerChan = " << description.mBitsPerChannel);
//std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; //ATA_DEBUG(" aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked));
//std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl; //ATA_DEBUG(" bytesPerFrame = " << description.mBytesPerFrame);
//std::cout << " sample rate = " << description.mSampleRate << std::endl; //ATA_DEBUG(" sample rate = " << description.mSampleRate);
if ( description.mFormatID != kAudioFormatLinearPCM if ( description.mFormatID != kAudioFormatLinearPCM
|| description.mBitsPerChannel < 16) { || description.mBitsPerChannel < 16) {
description.mFormatID = kAudioFormatLinearPCM; description.mFormatID = kAudioFormatLinearPCM;
@ -720,11 +720,11 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &testDescription); result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &testDescription);
if (result == noErr) { if (result == noErr) {
setPhysicalFormat = true; setPhysicalFormat = true;
//std::cout << "Updated physical stream format:" << std::endl; //ATA_DEBUG("Updated physical stream format:");
//std::cout << " mBitsPerChan = " << testDescription.mBitsPerChannel << std::endl; //ATA_DEBUG(" mBitsPerChan = " << testDescription.mBitsPerChannel);
//std::cout << " aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; //ATA_DEBUG(" aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked));
//std::cout << " bytesPerFrame = " << testDescription.mBytesPerFrame << std::endl; //ATA_DEBUG(" bytesPerFrame = " << testDescription.mBytesPerFrame);
//std::cout << " sample rate = " << testDescription.mSampleRate << std::endl; //ATA_DEBUG(" sample rate = " << testDescription.mSampleRate);
break; break;
} }
} }
@ -969,7 +969,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::stopStream() {
if (m_private->drainCounter == 0) { if (m_private->drainCounter == 0) {
ethread::UniqueLock lck(m_mutex); ethread::UniqueLock lck(m_mutex);
m_private->drainCounter = 2; m_private->drainCounter = 2;
m_private->condition.wait(lck); m_private->m_semaphore.wait();
} }
result = AudioDeviceStop(m_private->id[0], &audio::orchestra::api::Core::callbackEvent); result = AudioDeviceStop(m_private->id[0], &audio::orchestra::api::Core::callbackEvent);
if (result != noErr) { if (result != noErr) {
@ -1039,7 +1039,7 @@ bool audio::orchestra::api::Core::callbackEvent(AudioDeviceID _deviceId,
new ethread::Thread(&audio::orchestra::api::Core::coreStopStream, this); new ethread::Thread(&audio::orchestra::api::Core::coreStopStream, this);
} else { } else {
// external call to stopStream() // external call to stopStream()
m_private->condition.notify_one(); m_private->m_semaphore.post();
} }
return true; return true;
} }

View File

@ -13,7 +13,9 @@
#include <audio/orchestra/Interface.hpp> #include <audio/orchestra/Interface.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <climits> extern "C" {
#include <limits.h>
}
#include <audio/orchestra/api/CoreIos.hpp> #include <audio/orchestra/api/CoreIos.hpp>
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::CoreIos::create() { ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::CoreIos::create() {
@ -132,7 +134,7 @@ void audio::orchestra::api::CoreIos::callBackEvent(void* _data,
int32_t _nbChunk, int32_t _nbChunk,
const audio::Time& _time) { const audio::Time& _time) {
int32_t doStopStream = 0; int32_t doStopStream = 0;
std::vector<enum audio::orchestra::status> status; etk::Vector<enum audio::orchestra::status> status;
if ( m_mode == audio::orchestra::mode_output if ( m_mode == audio::orchestra::mode_output
|| m_mode == audio::orchestra::mode_duplex) { || m_mode == audio::orchestra::mode_duplex) {
if (m_doConvertBuffer[modeToIdTable(audio::orchestra::mode_output)] == true) { if (m_doConvertBuffer[modeToIdTable(audio::orchestra::mode_output)] == true) {

View File

@ -23,11 +23,10 @@ ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Ds::create() {
// - Auto-call CoInitialize for DSOUND and ASIO platforms. // - Auto-call CoInitialize for DSOUND and ASIO platforms.
// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007 // Various revisions for RtAudio 4.0 by Gary Scavone, April 2007
// Changed device query structure for RtAudio 4.0.7, January 2010 // Changed device query structure for RtAudio 4.0.7, January 2010
extern "C" {
#include <dsound.h> #include <dsound.h>
#include <cassert> #include <assert.h>
#include <algorithm> }
#if defined(__MINGW32__) #if defined(__MINGW32__)
// missing from latest mingw winapi // missing from latest mingw winapi
#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */ #define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */
@ -377,7 +376,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
info.sampleRates.pushBack(rates[i]); info.sampleRates.pushBack(rates[i]);
} }
} }
std::sort(info.sampleRates.begin(), info.sampleRates.end()); info.sampleRates.sort(0, info.sampleRates.size(), [](const uint32_t& _left, const uint32_t& _right) { return _left < _right;});
// Copy name and return. // Copy name and return.
info.name = m_private->dsDevices[_device].name; info.name = m_private->dsDevices[_device].name;
info.isCorrect = true; info.isCorrect = true;
@ -762,7 +761,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
// Setup the callback thread. // Setup the callback thread.
if (m_private->threadRunning == false) { if (m_private->threadRunning == false) {
m_private->threadRunning = true; m_private->threadRunning = true;
ememory::SharedPtr<ethread::Thread> tmpThread(new std::thread(&audio::orchestra::api::Ds::dsCallbackEvent, this)); ememory::SharedPtr<ethread::Thread> tmpThread(new ethread::Thread([=](){audio::orchestra::api::Ds::dsCallbackEvent();});
m_private->thread = etk::move(tmpThread); m_private->thread = etk::move(tmpThread);
if (m_private->thread == nullptr) { if (m_private->thread == nullptr) {
ATA_ERROR("error creating callback thread!"); ATA_ERROR("error creating callback thread!");
@ -1154,7 +1153,7 @@ void audio::orchestra::api::Ds::callbackEvent() {
// safeWritePointer and leadPointer. If leadPointer is not // safeWritePointer and leadPointer. If leadPointer is not
// beyond the next endWrite position, wait until it is. // beyond the next endWrite position, wait until it is.
leadPointer = safeWritePointer + m_private->dsPointerLeadTime[0]; leadPointer = safeWritePointer + m_private->dsPointerLeadTime[0];
//std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl; //ATA_DEBUG("safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer);
if (leadPointer > dsBufferSize) { if (leadPointer > dsBufferSize) {
leadPointer -= dsBufferSize; leadPointer -= dsBufferSize;
} }

View File

@ -7,12 +7,12 @@
// must run before : // must run before :
#if defined(ORCHESTRA_BUILD_JACK) #if defined(ORCHESTRA_BUILD_JACK)
extern "C" {
#include <climits> #include <limits.h>
#include <iostream> #include <string.h>
}
#include <audio/orchestra/Interface.hpp> #include <audio/orchestra/Interface.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <cstring>
#include <ethread/tools.hpp> #include <ethread/tools.hpp>
#include <audio/orchestra/api/Jack.hpp> #include <audio/orchestra/api/Jack.hpp>
@ -52,9 +52,9 @@ ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Jack::create()
// stream cannot be opened. // stream cannot be opened.
#include <jack/jack.h> #include <jack/jack.h>
extern "C" {
#include <cstdio> #include <stdio.h>
}
namespace audio { namespace audio {
namespace orchestra { namespace orchestra {
@ -65,7 +65,7 @@ namespace audio {
jack_port_t **ports[2]; jack_port_t **ports[2];
etk::String deviceName[2]; etk::String deviceName[2];
bool xrun[2]; bool xrun[2];
std::condition_variable condition; ethread::Semaphore m_semaphore;
int32_t drainCounter; // Tracks callback counts when draining int32_t drainCounter; // Tracks callback counts when draining
bool internalDrain; // Indicates if stop is initiated from callback or not. bool internalDrain; // Indicates if stop is initiated from callback or not.
@ -113,7 +113,7 @@ uint32_t audio::orchestra::api::Jack::getDeviceCount() {
port = (char *) ports[ nChannels ]; port = (char *) ports[ nChannels ];
iColon = port.find(":"); iColon = port.find(":");
if (iColon != etk::String::npos) { if (iColon != etk::String::npos) {
port = port.substr(0, iColon + 1); port = port.extract(0, iColon + 1);
if (port != previousPort) { if (port != previousPort) {
nDevices++; nDevices++;
previousPort = port; previousPort = port;
@ -121,6 +121,7 @@ uint32_t audio::orchestra::api::Jack::getDeviceCount() {
} }
} while (ports[++nChannels]); } while (ports[++nChannels]);
free(ports); free(ports);
ports = nullptr;
} }
jack_client_close(client); jack_client_close(client);
return nDevices*2; return nDevices*2;
@ -150,7 +151,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t
port = (char *) ports[nPorts]; port = (char *) ports[nPorts];
iColon = port.find(":"); iColon = port.find(":");
if (iColon != etk::String::npos) { if (iColon != etk::String::npos) {
port = port.substr(0, iColon); port = port.extract(0, iColon);
if (port != previousPort) { if (port != previousPort) {
if (nDevices == deviceID) { if (nDevices == deviceID) {
info.name = port; info.name = port;
@ -223,15 +224,6 @@ int32_t audio::orchestra::api::Jack::jackCallbackHandler(jack_nframes_t _nframes
return 0; return 0;
} }
// This function will be called by a spawned thread when the Jack
// server signals that it is shutting down. It is necessary to handle
// it this way because the jackShutdown() function must return before
// the jack_deactivate() function (in closeStream()) will return.
void audio::orchestra::api::Jack::jackCloseStream(void* _userData) {
ethread::setName("Jack_closeStream");
audio::orchestra::api::Jack* myClass = reinterpret_cast<audio::orchestra::api::Jack*>(_userData);
myClass->closeStream();
}
void audio::orchestra::api::Jack::jackShutdown(void* _userData) { void audio::orchestra::api::Jack::jackShutdown(void* _userData) {
audio::orchestra::api::Jack* myClass = reinterpret_cast<audio::orchestra::api::Jack*>(_userData); audio::orchestra::api::Jack* myClass = reinterpret_cast<audio::orchestra::api::Jack*>(_userData);
@ -243,7 +235,7 @@ void audio::orchestra::api::Jack::jackShutdown(void* _userData) {
if (myClass->isStreamRunning() == false) { if (myClass->isStreamRunning() == false) {
return; return;
} }
new ethread::Thread(&audio::orchestra::api::Jack::jackCloseStream, _userData); new ethread::Thread([=](){myClass->closeStream();});
ATA_ERROR("The Jack server is shutting down this client ... stream stopped and closed!!"); ATA_ERROR("The Jack server is shutting down this client ... stream stopped and closed!!");
} }
@ -273,7 +265,7 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
&& m_mode != audio::orchestra::mode_output)) { && m_mode != audio::orchestra::mode_output)) {
jack_options_t jackoptions = (jack_options_t) (JackNoStartServer); //JackNullOption; jack_options_t jackoptions = (jack_options_t) (JackNoStartServer); //JackNullOption;
jack_status_t *status = nullptr; jack_status_t *status = nullptr;
if (!_options.streamName.empty()) { if (_options.streamName.size() != 0) {
client = jack_client_open(_options.streamName.c_str(), jackoptions, status); client = jack_client_open(_options.streamName.c_str(), jackoptions, status);
} else { } else {
client = jack_client_open("orchestraJack", jackoptions, status); client = jack_client_open("orchestraJack", jackoptions, status);
@ -299,7 +291,7 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
port = (char *) ports[ nPorts ]; port = (char *) ports[ nPorts ];
iColon = port.find(":"); iColon = port.find(":");
if (iColon != etk::String::npos) { if (iColon != etk::String::npos) {
port = port.substr(0, iColon); port = port.extract(0, iColon);
if (port != previousPort) { if (port != previousPort) {
if (nDevices == deviceID) { if (nDevices == deviceID) {
deviceName = port; deviceName = port;
@ -597,8 +589,7 @@ enum audio::orchestra::error audio::orchestra::api::Jack::stopStream() {
|| m_mode == audio::orchestra::mode_duplex) { || m_mode == audio::orchestra::mode_duplex) {
if (m_private->drainCounter == 0) { if (m_private->drainCounter == 0) {
m_private->drainCounter = 2; m_private->drainCounter = 2;
ethread::UniqueLock lck(m_mutex); m_private->m_semaphore.wait();
m_private->condition.wait(lck);
} }
} }
jack_deactivate(m_private->client); jack_deactivate(m_private->client);
@ -618,17 +609,6 @@ enum audio::orchestra::error audio::orchestra::api::Jack::abortStream() {
return stopStream(); return stopStream();
} }
// This function will be called by a spawned thread when the user
// callback function signals that the stream should be stopped or
// aborted. It is necessary to handle it this way because the
// callbackEvent() function must return before the jack_deactivate()
// function will return.
static void jackStopStream(void* _userData) {
ethread::setName("Jack_stopStream");
audio::orchestra::api::Jack* myClass = reinterpret_cast<audio::orchestra::api::Jack*>(_userData);
myClass->stopStream();
}
bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) { bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) {
if ( m_state == audio::orchestra::state::stopped if ( m_state == audio::orchestra::state::stopped
|| m_state == audio::orchestra::state::stopping) { || m_state == audio::orchestra::state::stopping) {
@ -646,9 +626,9 @@ bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) {
if (m_private->drainCounter > 3) { if (m_private->drainCounter > 3) {
m_state = audio::orchestra::state::stopping; m_state = audio::orchestra::state::stopping;
if (m_private->internalDrain == true) { if (m_private->internalDrain == true) {
new ethread::Thread(jackStopStream, this); new ethread::Thread([&](){stopStream();}, "Jack_stopStream");
} else { } else {
m_private->condition.notify_one(); m_private->m_semaphore.post();
} }
return true; return true;
} }
@ -673,7 +653,7 @@ bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) {
if (cbReturnValue == 2) { if (cbReturnValue == 2) {
m_state = audio::orchestra::state::stopping; m_state = audio::orchestra::state::stopping;
m_private->drainCounter = 2; m_private->drainCounter = 2;
new ethread::Thread(jackStopStream, this); new ethread::Thread([&](){stopStream();}, "Jack_stopStream2");
return true; return true;
} }
else if (cbReturnValue == 1) { else if (cbReturnValue == 1) {

View File

@ -36,7 +36,6 @@ namespace audio {
bool callbackEvent(uint64_t _nframes); bool callbackEvent(uint64_t _nframes);
private: private:
static int32_t jackXrun(void* _userData); static int32_t jackXrun(void* _userData);
static void jackCloseStream(void* _userData);
static void jackShutdown(void* _userData); static void jackShutdown(void* _userData);
static int32_t jackCallbackHandler(jack_nframes_t _nframes, void* _userData); static int32_t jackCallbackHandler(jack_nframes_t _nframes, void* _userData);
private: private:

View File

@ -8,13 +8,14 @@
#if defined(ORCHESTRA_BUILD_PULSE) #if defined(ORCHESTRA_BUILD_PULSE)
extern "C" {
#include <climits> #include <limits.h>
#include <stdio.h>
}
#include <audio/orchestra/Interface.hpp> #include <audio/orchestra/Interface.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <pulse/error.h> #include <pulse/error.h>
#include <pulse/simple.h> #include <pulse/simple.h>
#include <cstdio>
#include <ethread/tools.hpp> #include <ethread/tools.hpp>
#include <audio/orchestra/api/PulseDeviceList.hpp> #include <audio/orchestra/api/PulseDeviceList.hpp>
#include <audio/orchestra/api/Pulse.hpp> #include <audio/orchestra/api/Pulse.hpp>
@ -55,7 +56,7 @@ namespace audio {
pa_simple* handle; pa_simple* handle;
ememory::SharedPtr<ethread::Thread> thread; ememory::SharedPtr<ethread::Thread> thread;
bool threadRunning; bool threadRunning;
std::condition_variable runnable_cv; ethread::Semaphore m_semaphore;
bool runnable; bool runnable;
PulsePrivate() : PulsePrivate() :
handle(0), handle(0),
@ -96,10 +97,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Pulse::getDeviceInfo(uint32_
return list[_device]; return list[_device];
} }
static void pulseaudio_callback(void* _userData) {
audio::orchestra::api::Pulse* myClass = reinterpret_cast<audio::orchestra::api::Pulse*>(_userData);
myClass->callbackEvent();
}
void audio::orchestra::api::Pulse::callbackEvent() { void audio::orchestra::api::Pulse::callbackEvent() {
ethread::setName("Pulse IO-" + m_name); ethread::setName("Pulse IO-" + m_name);
@ -113,9 +111,9 @@ enum audio::orchestra::error audio::orchestra::api::Pulse::closeStream() {
m_mutex.lock(); m_mutex.lock();
if (m_state == audio::orchestra::state::stopped) { if (m_state == audio::orchestra::state::stopped) {
m_private->runnable = true; m_private->runnable = true;
m_private->runnable_cv.notify_one();; m_private->m_semaphore.post();;
} }
m_mutex.unlock(); m_mutex.unLock();
m_private->thread->join(); m_private->thread->join();
if (m_mode == audio::orchestra::mode_output) { if (m_mode == audio::orchestra::mode_output) {
pa_simple_flush(m_private->handle, nullptr); pa_simple_flush(m_private->handle, nullptr);
@ -131,12 +129,11 @@ enum audio::orchestra::error audio::orchestra::api::Pulse::closeStream() {
void audio::orchestra::api::Pulse::callbackEventOneCycle() { void audio::orchestra::api::Pulse::callbackEventOneCycle() {
if (m_state == audio::orchestra::state::stopped) { if (m_state == audio::orchestra::state::stopped) {
ethread::UniqueLock lck(m_mutex);
while (!m_private->runnable) { while (!m_private->runnable) {
m_private->runnable_cv.wait(lck); m_private->m_semaphore.wait();
} }
if (m_state != audio::orchestra::state::running) { if (m_state != audio::orchestra::state::running) {
m_mutex.unlock(); m_mutex.unLock();
return; return;
} }
} }
@ -160,7 +157,7 @@ void audio::orchestra::api::Pulse::callbackEventOneCycle() {
void *pulse_in = m_doConvertBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)] ? m_deviceBuffer : &m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)][0]; void *pulse_in = m_doConvertBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)] ? m_deviceBuffer : &m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)][0];
void *pulse_out = m_doConvertBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)] ? m_deviceBuffer : &m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)][0]; void *pulse_out = m_doConvertBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)] ? m_deviceBuffer : &m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)][0];
if (m_state != audio::orchestra::state::running) { if (m_state != audio::orchestra::state::running) {
goto unlock; goto unLock;
} }
int32_t pa_error; int32_t pa_error;
size_t bytes; size_t bytes;
@ -194,8 +191,8 @@ void audio::orchestra::api::Pulse::callbackEventOneCycle() {
m_convertInfo[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)]); m_convertInfo[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)]);
} }
} }
unlock: unLock:
m_mutex.unlock(); m_mutex.unLock();
audio::orchestra::Api::tickStreamTime(); audio::orchestra::Api::tickStreamTime();
if (doStopStream == 1) { if (doStopStream == 1) {
stopStream(); stopStream();
@ -218,8 +215,8 @@ enum audio::orchestra::error audio::orchestra::api::Pulse::startStream() {
m_mutex.lock(); m_mutex.lock();
m_state = audio::orchestra::state::running; m_state = audio::orchestra::state::running;
m_private->runnable = true; m_private->runnable = true;
m_private->runnable_cv.notify_one(); m_private->m_semaphore.post();
m_mutex.unlock(); m_mutex.unLock();
return audio::orchestra::error_none; return audio::orchestra::error_none;
} }
@ -240,12 +237,12 @@ enum audio::orchestra::error audio::orchestra::api::Pulse::stopStream() {
int32_t pa_error; int32_t pa_error;
if (pa_simple_drain(m_private->handle, &pa_error) < 0) { if (pa_simple_drain(m_private->handle, &pa_error) < 0) {
ATA_ERROR("error draining output device, " << pa_strerror(pa_error) << "."); ATA_ERROR("error draining output device, " << pa_strerror(pa_error) << ".");
m_mutex.unlock(); m_mutex.unLock();
return audio::orchestra::error_systemError; return audio::orchestra::error_systemError;
} }
} }
m_state = audio::orchestra::state::stopped; m_state = audio::orchestra::state::stopped;
m_mutex.unlock(); m_mutex.unLock();
return audio::orchestra::error_none; return audio::orchestra::error_none;
} }
@ -266,12 +263,12 @@ enum audio::orchestra::error audio::orchestra::api::Pulse::abortStream() {
int32_t pa_error; int32_t pa_error;
if (pa_simple_flush(m_private->handle, &pa_error) < 0) { if (pa_simple_flush(m_private->handle, &pa_error) < 0) {
ATA_ERROR("error flushing output device, " << pa_strerror(pa_error) << "."); ATA_ERROR("error flushing output device, " << pa_strerror(pa_error) << ".");
m_mutex.unlock(); m_mutex.unLock();
return audio::orchestra::error_systemError; return audio::orchestra::error_systemError;
} }
} }
m_state = audio::orchestra::state::stopped; m_state = audio::orchestra::state::stopped;
m_mutex.unlock(); m_mutex.unLock();
return audio::orchestra::error_none; return audio::orchestra::error_none;
} }
@ -393,7 +390,7 @@ bool audio::orchestra::api::Pulse::open(uint32_t _device,
} }
if (m_private->threadRunning == false) { if (m_private->threadRunning == false) {
m_private->threadRunning = true; m_private->threadRunning = true;
m_private->thread = ememory::makeShared<ethread::Thread>(&pulseaudio_callback, this); m_private->thread = ememory::makeShared<ethread::Thread>([&](){callbackEvent();}, "pulseCallback");
if (m_private->thread == nullptr) { if (m_private->thread == nullptr) {
ATA_ERROR("error creating thread."); ATA_ERROR("error creating thread.");
goto error; goto error;

View File

@ -6,9 +6,10 @@
*/ */
#if defined(ORCHESTRA_BUILD_PULSE) #if defined(ORCHESTRA_BUILD_PULSE)
extern "C" {
#include <cstdio> #include <stdio.h>
#include <cstring> #include <string.h>
}
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
#include <audio/orchestra/api/PulseDeviceList.hpp> #include <audio/orchestra/api/PulseDeviceList.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>

View File

@ -7,9 +7,9 @@
#pragma once #pragma once
#include <ethread/Thread.hpp> #include <ethread/Thread.hpp>
#include <condition_variable> #include <ethread/Semaphore.hpp>
#include <ethread/Mutex.hpp> #include <ethread/Mutex.hpp>
#include <chrono> #include <echrono/Steady.hpp>
#include <etk/Function.hpp> #include <etk/Function.hpp>
#include <ememory/memory.hpp> #include <ememory/memory.hpp>
#include <audio/channel.hpp> #include <audio/channel.hpp>

View File

@ -36,4 +36,4 @@ etk::Stream& audio::operator <<(etk::Stream& _os, enum audio::orchestra::mode _o
break; break;
} }
return _os; return _os;
} }

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <etk/types.hpp> #include <etk/types.hpp>
#include <etk/Stream.hpp>
namespace audio { namespace audio {
namespace orchestra { namespace orchestra {

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <etk/types.hpp> #include <etk/types.hpp>
#include <etk/Vector.hpp>
namespace audio { namespace audio {
namespace orchestra { namespace orchestra {

View File

@ -7,10 +7,6 @@
#include <audio/orchestra/type.hpp> #include <audio/orchestra/type.hpp>
#include <audio/orchestra/debug.hpp> #include <audio/orchestra/debug.hpp>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <climits>
const etk::String audio::orchestra::typeUndefined = "undefined"; const etk::String audio::orchestra::typeUndefined = "undefined";
const etk::String audio::orchestra::typeAlsa = "alsa"; const etk::String audio::orchestra::typeAlsa = "alsa";

View File

@ -16,8 +16,8 @@ int main(int _argc, const char **_argv) {
etk::String data = _argv[iii]; etk::String data = _argv[iii];
if ( data == "-h" if ( data == "-h"
|| data == "--help") { || data == "--help") {
std::cout << "Help : " << std::endl; TEST_PRINT("Help : ");
std::cout << " ./xxx ---" << std::endl; TEST_PRINT(" ./xxx ---");
exit(0); exit(0);
} }
} }

View File

@ -16,8 +16,8 @@ int main(int _argc, const char **_argv) {
etk::String data = _argv[iii]; etk::String data = _argv[iii];
if ( data == "-h" if ( data == "-h"
|| data == "--help") { || data == "--help") {
std::cout << "Help : " << std::endl; TEST_PRINT("Help : ");
std::cout << " ./xxx ---" << std::endl; TEST_PRINT(" ./xxx ---");
exit(0); exit(0);
} }
} }

View File

@ -16,8 +16,8 @@ int main(int _argc, const char **_argv) {
etk::String data = _argv[iii]; etk::String data = _argv[iii];
if ( data == "-h" if ( data == "-h"
|| data == "--help") { || data == "--help") {
std::cout << "Help : " << std::endl; TEST_PRINT("Help : ");
std::cout << " ./xxx ---" << std::endl; TEST_PRINT(" ./xxx ---");
exit(0); exit(0);
} }
} }