[DEV] many internal change and add linker alsa flow

This commit is contained in:
2015-02-27 21:07:17 +01:00
parent a5dbe5a607
commit 8f3d17fdf8
28 changed files with 244 additions and 113 deletions

View File

@@ -14,6 +14,7 @@
#include <airtaudio/debug.h>
#include <etk/stdTools.h>
#include <limits.h>
#include <airtaudio/api/Alsa.h>
#undef __class__
#define __class__ "api::Alsa"
@@ -33,13 +34,13 @@ namespace airtaudio {
bool runnable;
std11::thread* thread;
bool threadRunning;
bool isMonotonic; //!< the timestamp of the flow came from the harware.
enum timestampMode timeMode; //!< the timestamp of the flow came from the harware.
AlsaPrivate() :
synchronized(false),
runnable(false),
thread(nullptr),
threadRunning(false),
isMonotonic(false) {
timeMode(timestampMode_soft) {
handles[0] = nullptr;
handles[1] = nullptr;
xrun[0] = false;
@@ -406,7 +407,7 @@ bool airtaudio::api::Alsa::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio::StreamOptions& _options) {
// I'm not using the "plug" interface ... too much inconsistent behavior.
unsigned nDevices = 0;
int32_t result, subdevice, card;
@@ -461,7 +462,7 @@ bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio::StreamOptions& _options) {
// I'm not using the "plug" interface ... too much inconsistent behavior.
unsigned nDevices = 0;
int32_t result, subdevice, card;
@@ -608,14 +609,12 @@ bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
*_bufferSize = periodSize;
// Set the buffer number, which in ALSA is referred to as the "period".
uint32_t periods = 0;
if ( _options != nullptr
&& _options->flags.m_minimizeLatency == true) {
if (_options.flags.m_minimizeLatency == true) {
periods = 2;
}
/* TODO : Chouse the number of low level buffer ...
if ( _options != nullptr
&& _options->numberOfBuffers > 0) {
periods = _options->numberOfBuffers;
if (_options.numberOfBuffers > 0) {
periods = _options.numberOfBuffers;
}
*/
if (periods < 2) {
@@ -639,11 +638,16 @@ bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
m_bufferSize = *_bufferSize;
// check if the hardware provide hardware clock :
if (snd_pcm_hw_params_is_monotonic(hw_params) == 0) {
m_private->isMonotonic = false;
ATA_WARNING("ALSA Audio timestamp is NOT monotonic (Generate with the start timestamp)");
ATA_INFO("ALSA Audio timestamp is NOT monotonic (Generate with the start timestamp)");
if (_options.mode == timestampMode_Hardware) {
ATA_WARNING("Can not select Harware timeStamp ==> the IO is not monotonic ==> select ");
m_private->timeMode = timestampMode_trigered;
} else {
m_private->timeMode = _options.mode;
}
} else {
m_private->isMonotonic = true;
ATA_DEBUG("ALSA Audio timestamp is monotonic (came from harware)");
ATA_DEBUG("ALSA Audio timestamp is monotonic (can came from harware)");
m_private->timeMode = _options.mode;
}
// Install the hardware configuration
@@ -976,7 +980,7 @@ void airtaudio::api::Alsa::callbackEvent() {
}
std11::chrono::system_clock::time_point airtaudio::api::Alsa::getStreamTime() {
if (m_private->isMonotonic == true) {
if (m_private->timeMode == timestampMode_Hardware) {
snd_pcm_status_t *status = nullptr;
snd_pcm_status_alloca(&status);
// get harware timestamp all the time:
@@ -988,9 +992,6 @@ std11::chrono::system_clock::time_point airtaudio::api::Alsa::getStreamTime() {
ATA_WARNING(" get time of the signal error ...");
return m_startTime + m_duration;
}
// get start time:
//snd_pcm_status_get_trigger_tstamp(status, &timestamp);
//m_startTime = std11::chrono::system_clock::from_time_t(timestamp.tv_sec) + std11::chrono::microseconds(timestamp.tv_usec);
#if 0
snd_timestamp_t timestamp;
snd_pcm_status_get_tstamp(status, &timestamp);
@@ -1013,7 +1014,28 @@ std11::chrono::system_clock::time_point airtaudio::api::Alsa::getStreamTime() {
m_startTime -= timeDelay;
}
return m_startTime;
} else if (m_private->timeMode == timestampMode_trigered) {
if (m_startTime == std11::chrono::system_clock::time_point()) {
snd_pcm_status_t *status = nullptr;
snd_pcm_status_alloca(&status);
// get harware timestamp all the time:
if (m_private->handles[0] != nullptr) {
snd_pcm_status(m_private->handles[0], status);
} else if (m_private->handles[1] != nullptr) {
snd_pcm_status(m_private->handles[1], status);
} else {
ATA_WARNING(" get time of the signal error ...");
return m_startTime + m_duration;
}
// get start time:
snd_timestamp_t timestamp;
snd_pcm_status_get_trigger_tstamp(status, &timestamp);
m_startTime = std11::chrono::system_clock::from_time_t(timestamp.tv_sec) + std11::chrono::microseconds(timestamp.tv_usec);
ATA_VERBOSE("snd_pcm_status_get_trigger_tstamp : " << m_startTime);
}
return m_startTime + m_duration;
} else {
// softaware mode ...
if (m_startTime == std11::chrono::system_clock::time_point()) {
m_startTime = std11::chrono::system_clock::now();
std11::chrono::nanoseconds timeDelay(m_bufferSize*1000000000LL/int64_t(m_sampleRate));
@@ -1209,5 +1231,48 @@ unlock:
}
}
bool airtaudio::api::Alsa::isMasterOf(airtaudio::Api* _api) {
airtaudio::api::Alsa* slave = dynamic_cast<airtaudio::api::Alsa*>(_api);
if (slave == nullptr) {
ATA_ERROR("NULL ptr API (not ALSA ...)");
return false;
}
if (m_state == airtaudio::state_running) {
ATA_ERROR("The MASTER stream is already running! ==> can not synchronize ...");
return false;
}
if (slave->m_state == airtaudio::state_running) {
ATA_ERROR("The SLAVE stream is already running! ==> can not synchronize ...");
return false;
}
snd_pcm_t * master = nullptr;
if (m_private->handles[0] != nullptr) {
master = m_private->handles[0];
}
if (m_private->handles[1] != nullptr) {
master = m_private->handles[1];
}
if (master == nullptr) {
ATA_ERROR("No ALSA handles ...");
return false;
}
ATA_INFO(" ==> plop");
if (slave->m_private->handles[0] != nullptr) {
if (snd_pcm_link(master, slave->m_private->handles[0]) != 0) {
ATA_ERROR("Can not syncronize handle output");
} else {
ATA_INFO(" -------------------- LINK 0 --------------------");
}
}
if (slave->m_private->handles[1] != nullptr) {
if (snd_pcm_link(master, slave->m_private->handles[1]) != 0) {
ATA_ERROR("Can not syncronize handle input");
} else {
ATA_INFO(" -------------------- LINK 1 --------------------");
}
}
return true;
}
#endif

View File

@@ -55,7 +55,7 @@ namespace airtaudio {
uint32_t _sampleRate,
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio::StreamOptions& _options);
virtual bool probeDeviceOpenName(const std::string& _deviceName,
airtaudio::mode _mode,
@@ -64,8 +64,10 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio::StreamOptions& _options);
virtual std11::chrono::system_clock::time_point getStreamTime();
public:
bool isMasterOf(airtaudio::Api* _api);
};
};
};

View File

@@ -153,7 +153,7 @@ bool airtaudio::api::Android::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio::StreamOptions& _options) {
ATA_INFO("Probe : device=" << _device << " channels=" << _channels << " firstChannel=" << _firstChannel << " sampleRate=" << _sampleRate);
if (_mode != airtaudio::mode_output) {
ATA_ERROR("Can not start a device input or duplex for Android ...");

View File

@@ -40,7 +40,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio::StreamOptions& _options);
private:
void callBackEvent(void* _data,
int32_t _frameRate);

View File

@@ -224,7 +224,7 @@ bool airtaudio::api::Asio::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t* _bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio::StreamOptions& _options) {
// For ASIO, a duplex stream MUST use the same driver.
if ( _mode == airtaudio::mode_input
&& m_mode == airtaudio::mode_output

View File

@@ -44,7 +44,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
};
};
};

View File

@@ -428,7 +428,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio.::StreamOptions& _options) {
// Get device ID
uint32_t nDevices = getDeviceCount();
if (nDevices == 0) {
@@ -569,8 +569,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
} else if (bufferRange.mMaximum < *_bufferSize) {
*_bufferSize = (uint64_t) bufferRange.mMaximum;
}
if ( _options != nullptr
&& _options->flags.m_minimizeLatency == true) {
if (_options.flags.m_minimizeLatency == true) {
*_bufferSize = (uint64_t) bufferRange.mMinimum;
}
// Set the buffer size. For multiple streams, I'm assuming we only

View File

@@ -53,7 +53,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
static const char* getErrorCode(OSStatus _code);
static OSStatus xrunListener(AudioObjectID _inDevice,
uint32_t _nAddresses,

View File

@@ -41,7 +41,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
public:
void callBackEvent(void* _data,
int32_t _frameRate);

View File

@@ -182,7 +182,7 @@ bool airtaudio::api::CoreIos::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio.::StreamOptions& _options) {
ATA_INFO("Probe : device=" << _device << " channels=" << _channels << " firstChannel=" << _firstChannel << " sampleRate=" << _sampleRate);
if (_mode != airtaudio::mode_output) {
ATA_ERROR("Can not start a device input or duplex for CoreIos ...");

View File

@@ -361,7 +361,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio.::StreamOptions& _options) {
if (_channels + _firstChannel > 2) {
ATA_ERROR("DirectSound does not support more than 2 channels per device.");
return false;
@@ -402,12 +402,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
// low for capture, but it should work for playback.
int32_t nBuffers = 0;
/*
if (_options != nullptr) {
nBuffers = _options->numberOfBuffers;
}
nBuffers = _options.numberOfBuffers;
*/
if ( _options!= nullptr
&& _options->flags.m_minimizeLatency == true) {
if (_options.flags.m_minimizeLatency == true) {
nBuffers = 2;
}
if (nBuffers < 2) {

View File

@@ -47,7 +47,7 @@ namespace airtaudio {
uint32_t _sampleRate,
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
};
};
};

View File

@@ -55,7 +55,7 @@ bool airtaudio::api::Dummy::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio::StreamOptions& _options) {
return false;
}

View File

@@ -34,7 +34,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio::StreamOptions& _options);
};
};
};

View File

@@ -268,7 +268,7 @@ bool airtaudio::api::Jack::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t* _bufferSize,
airtaudio::StreamOptions* _options) {
const airtaudio.::StreamOptions& _options) {
// Look for jack server and try to become a client (only do once per stream).
jack_client_t *client = 0;
if ( _mode == airtaudio::mode_output
@@ -276,8 +276,8 @@ bool airtaudio::api::Jack::probeDeviceOpen(uint32_t _device,
&& m_mode != airtaudio::mode_output)) {
jack_options_t jackoptions = (jack_options_t) (JackNoStartServer); //JackNullOption;
jack_status_t *status = nullptr;
if (_options && !_options->streamName.empty()) {
client = jack_client_open(_options->streamName.c_str(), jackoptions, status);
if (!_options.streamName.empty()) {
client = jack_client_open(_options.streamName.c_str(), jackoptions, status);
} else {
client = jack_client_open("airtaudioJack", jackoptions, status);
}

View File

@@ -47,7 +47,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
};
};
};

View File

@@ -187,7 +187,7 @@ bool airtaudio::api::Oss::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
rtaudio::format _format,
uint32_t* _bufferSize,
rtaudio::StreamOptions* _options) {
const airtaudio.::StreamOptions& _options) {
int32_t mixerfd = open("/dev/mixer", O_RDWR, 0);
if (mixerfd == -1) {
ATA_ERROR("error opening '/dev/mixer'.");
@@ -257,8 +257,7 @@ bool airtaudio::api::Oss::probeDeviceOpen(uint32_t _device,
}
}
// Set exclusive access if specified.
if ( _options != nullptr
&& _options->flags & RTAUDIO_HOG_DEVICE) {
if (_options.flags & RTAUDIO_HOG_DEVICE) {
flags |= O_EXCL;
}
// Try to open the device.
@@ -400,11 +399,8 @@ bool airtaudio::api::Oss::probeDeviceOpen(uint32_t _device,
ossBufferBytes = 16;
}
int32_t buffers = 0;
if (_options != nullptr) {
buffers = _options->numberOfBuffers;
}
if ( _options != nullptr
&& _options->flags.m_minimizeLatency == true) {
buffers = _options.numberOfBuffers;
if (_options.flags.m_minimizeLatency == true) {
buffers = 2;
}
if (buffers < 2) {

View File

@@ -40,7 +40,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
};
};
};

View File

@@ -285,7 +285,7 @@ bool airtaudio::api::Pulse::probeDeviceOpen(uint32_t _device,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options) {
const airtaudio.::StreamOptions& _options) {
uint64_t bufferBytes = 0;
pa_sample_spec ss;
if (_device != 0) {

View File

@@ -43,7 +43,7 @@ namespace airtaudio {
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
const airtaudio.::StreamOptions& _options);
};
};
};