Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
465c1334bd | |||
d1b0a4a664 | |||
5a9c89e4fe | |||
69f60f45fe | |||
28237ad66f | |||
0b8c0e3fd4 | |||
309b63254f | |||
4bc3ff2f1a | |||
dfc867db87 | |||
a4ba319ffc | |||
bcff6508ab | |||
2a9f28b962 | |||
c3a13b4a39 | |||
7ab2025721 | |||
34eb6d5cf0 | |||
429a1cd062 | |||
6e534cbf22 | |||
c7d5c42ea8 | |||
918d573f18 | |||
fe23d699d1 | |||
e0a01e4280 | |||
fd1651924a | |||
ecb2b4d99e | |||
276e4ce356 | |||
943323947d | |||
62c2f2fd25 | |||
9a96211853 | |||
7e104a1f72 | |||
94e2bbabe3 | |||
b1eebd75e9 | |||
8174d45416 | |||
db89c092be | |||
151a3ddcf4 | |||
bc78a1858a | |||
f4f1ee888b |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,8 @@
|
|||||||
|
__pycache__
|
||||||
|
.bck
|
||||||
|
out
|
||||||
|
target
|
||||||
|
build
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
# folders
|
# folders
|
||||||
|
88
.travis.yml
88
.travis.yml
@@ -1,11 +1,7 @@
|
|||||||
language:
|
language: cpp
|
||||||
- cpp
|
|
||||||
|
|
||||||
sudo: false
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
@@ -18,33 +14,81 @@ addons:
|
|||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
packages:
|
packages:
|
||||||
- g++-4.9
|
- g++-4.9
|
||||||
|
- expect
|
||||||
|
- binutils-mingw-w64-x86-64 # 64bit MinGW
|
||||||
|
- gcc-mingw-w64-x86-64
|
||||||
|
- g++-mingw-w64-x86-64
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
env: CONF=release BUILDER=gcc TARGET=Linux TAG=Linux COMPILATOR_OPTION="--compilator-version=4.9" GCOV=--gcov
|
||||||
|
compiler: gcc
|
||||||
|
- os: linux
|
||||||
|
env: CONF=debug BUILDER=clang TARGET=Linux
|
||||||
|
compiler: clang
|
||||||
|
- os: linux
|
||||||
|
env: CONF=release BUILDER=gcc TARGET=Windows TAG=Mingw
|
||||||
|
compiler: x86_64-w64-mingw32-gcc
|
||||||
|
- os: linux
|
||||||
|
env: CONF=release BUILDER=gcc TARGET=Android TAG=Android DISABLE_PACKAGE=-p
|
||||||
|
compiler: gcc
|
||||||
|
- os: osx
|
||||||
|
env: CONF=release BUILDER=clang TARGET=MacOs TAG=MacOs
|
||||||
|
compiler: clang
|
||||||
|
- os: osx
|
||||||
|
env: CONF=release BUILDER=clang TARGET=IOs TAG=IOs
|
||||||
|
compiler: clang
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
- cd ..
|
||||||
- pip install --user lutin
|
- pip install --user lutin
|
||||||
|
- if [ "$TAG" == "Android" ]; then
|
||||||
env:
|
git clone --depth 1 --branch master https://github.com/HeeroYui/android-download-tool;
|
||||||
- CONF=debug BOARD=Linux BUILDER=clang GCOV=
|
./android-download-tool/dl-android.sh;
|
||||||
- CONF=release BOARD=Linux BUILDER=clang GCOV=
|
fi
|
||||||
- CONF=debug BOARD=Linux BUILDER=gcc GCOV=
|
- git clone --depth 1 --branch master https://github.com/atria-soft/ci.git
|
||||||
- CONF=release BOARD=Linux BUILDER=gcc GCOV=
|
- cd -
|
||||||
- CONF=debug BOARD=Linux BUILDER=gcc GCOV=--gcov
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- cd ..
|
- cd ..
|
||||||
- wget http://atria-soft.com/ci/coverage_send.py
|
- git clone https://github.com/atria-soft/etk.git -b $TRAVIS_BRANCH
|
||||||
- wget http://atria-soft.com/ci/test_send.py
|
- git clone https://github.com/atria-soft/elog.git -b $TRAVIS_BRANCH
|
||||||
- wget http://atria-soft.com/ci/warning_send.py
|
- git clone https://github.com/atria-soft/ememory.git -b $TRAVIS_BRANCH
|
||||||
- git clone https://github.com/atria-soft/etk.git
|
- git clone https://github.com/atria-soft/echrono.git -b $TRAVIS_BRANCH
|
||||||
- git clone https://github.com/musicdsp/audio.git
|
- git clone https://github.com/atria-soft/ethread.git -b $TRAVIS_BRANCH
|
||||||
|
- git clone https://github.com/atria-soft/ejson.git -b $TRAVIS_BRANCH
|
||||||
|
- git clone https://github.com/atria-soft/jvm-basics.git -b $TRAVIS_BRANCH
|
||||||
|
- git clone https://github.com/musicdsp/audio.git -b $TRAVIS_BRANCH
|
||||||
|
- git clone https://github.com/generic-library/gtest-lutin.git --recursive
|
||||||
|
- git clone https://github.com/generic-library/z-lutin.git --recursive
|
||||||
- pwd
|
- pwd
|
||||||
- ls -l
|
- ls -l
|
||||||
- if [ "$BUILDER" == "gcc" ]; then COMPILATOR_OPTION="--compilator-version=4.9"; else COMPILATOR_OPTION=""; fi
|
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||||
|
export PATH=$PATH:/Users/travis/Library/Python/2.7/bin/;
|
||||||
|
fi
|
||||||
|
- ./ci/build_send.py --tag=$TAG --status=START;
|
||||||
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- lutin -w -j4 -C -P -c $BUILDER $COMPILATOR_OPTION -m $CONF $GCOV -p audio-orchestra
|
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-orchestra; STATUS=$?
|
||||||
# - ./out/Linux_x86_64/$CONF/staging/$BUILDER/audio-orchestra/usr/bin/audio-orchestra -l6
|
- ./ci/build_send.py --tag=$TAG --status="$STATUS";
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
- if [ "$GCOV" != "" ]; then
|
||||||
|
./ci/warning_send.py --find-path ./out/Linux_x86_64/$CONF/build/$BUILDER/audio-orchestra/;
|
||||||
|
fi
|
||||||
|
#- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-orchestra-test?run:--elog-level=3 | tee out_test.txt
|
||||||
|
#- if [ "$GCOV" != "" ]; then
|
||||||
|
# ./ci/test_send.py --file=out_test.txt;
|
||||||
|
# lutin -C -P -t $TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF -p audio-orchestra?gcov;
|
||||||
|
# ./ci/coverage_send.py --json=out/Linux_x86_64/$CONF/build/$BUILDER/audio-orchestra/audio-orchestra_coverage.json;
|
||||||
|
# fi
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
- yui.heero@gmail.com
|
- yui.heero@gmail.com
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
174
GLD_audio-orchestra.json
Normal file
174
GLD_audio-orchestra.json
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
{
|
||||||
|
"type":"LIBRARY",
|
||||||
|
"group-id":"com.atria-soft",
|
||||||
|
"description":"Generic wrapper on all audio interface",
|
||||||
|
"license":"MPL-2",
|
||||||
|
"license-file":"file://LICENSE",
|
||||||
|
"maintainer":"file://authors.txt",
|
||||||
|
"author":"file://authors.txt",
|
||||||
|
"version":"file://version.txt",
|
||||||
|
"code-quality":"MEDIUM",
|
||||||
|
|
||||||
|
"source": [
|
||||||
|
"audio/orchestra/debug.cpp",
|
||||||
|
"audio/orchestra/status.cpp",
|
||||||
|
"audio/orchestra/type.cpp",
|
||||||
|
"audio/orchestra/mode.cpp",
|
||||||
|
"audio/orchestra/state.cpp",
|
||||||
|
"audio/orchestra/error.cpp",
|
||||||
|
"audio/orchestra/base.cpp",
|
||||||
|
"audio/orchestra/Interface.cpp",
|
||||||
|
"audio/orchestra/Flags.cpp",
|
||||||
|
"audio/orchestra/Api.cpp",
|
||||||
|
"audio/orchestra/DeviceInfo.cpp",
|
||||||
|
"audio/orchestra/StreamOptions.cpp",
|
||||||
|
"audio/orchestra/api/Dummy.cpp"
|
||||||
|
],
|
||||||
|
"header": [
|
||||||
|
"audio/orchestra/debug.hpp",
|
||||||
|
"audio/orchestra/status.hpp",
|
||||||
|
"audio/orchestra/type.hpp",
|
||||||
|
"audio/orchestra/mode.hpp",
|
||||||
|
"audio/orchestra/state.hpp",
|
||||||
|
"audio/orchestra/error.hpp",
|
||||||
|
"audio/orchestra/base.hpp",
|
||||||
|
"audio/orchestra/Interface.hpp",
|
||||||
|
"audio/orchestra/Flags.hpp",
|
||||||
|
"audio/orchestra/Api.hpp",
|
||||||
|
"audio/orchestra/DeviceInfo.hpp",
|
||||||
|
"audio/orchestra/StreamOptions.hpp",
|
||||||
|
"audio/orchestra/CallbackInfo.hpp",
|
||||||
|
"audio/orchestra/StreamParameters.hpp"
|
||||||
|
],
|
||||||
|
"path":[
|
||||||
|
"."
|
||||||
|
],
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_DUMMY"
|
||||||
|
},
|
||||||
|
"compilation-version": {
|
||||||
|
"c++": 2017
|
||||||
|
},
|
||||||
|
"dependency": [
|
||||||
|
"audio",
|
||||||
|
"etk"
|
||||||
|
],
|
||||||
|
"target":{
|
||||||
|
"Windows":{
|
||||||
|
"dependency": [
|
||||||
|
{
|
||||||
|
"name": "asio",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_ASIO"
|
||||||
|
},
|
||||||
|
"source": "audio/orchestra/api/Asio.cpp"
|
||||||
|
},{
|
||||||
|
"name": "ds",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_DS"
|
||||||
|
},
|
||||||
|
"source": "audio/orchestra/api/Ds.cpp"
|
||||||
|
},{
|
||||||
|
"name": "wasapi",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_WASAPI"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Linux":{
|
||||||
|
"dependency": [
|
||||||
|
{
|
||||||
|
"name": "alsa",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_ALSA"
|
||||||
|
},
|
||||||
|
"source": "audio/orchestra/api/Alsa.cpp"
|
||||||
|
},{
|
||||||
|
"name": "jack",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_JACK"
|
||||||
|
},
|
||||||
|
"source": "audio/orchestra/api/Jack.cpp"
|
||||||
|
},{
|
||||||
|
"name": "pulse",
|
||||||
|
"optional": true,
|
||||||
|
"export": true,
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_PULSE"
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"audio/orchestra/api/Pulse.cpp",
|
||||||
|
"audio/orchestra/api/PulseDeviceList.cpp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"MacOs":{
|
||||||
|
"source": [
|
||||||
|
"audio/orchestra/api/Core.cpp"
|
||||||
|
],
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_MACOSX_CORE"
|
||||||
|
},
|
||||||
|
"dependency": [
|
||||||
|
"CoreAudio"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"IOs":{
|
||||||
|
"source": [
|
||||||
|
"audio/orchestra/api/CoreIos.mm"
|
||||||
|
],
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_IOS_CORE"
|
||||||
|
},
|
||||||
|
"dependency": [
|
||||||
|
"CoreAudio"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Android":{
|
||||||
|
"source": [
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraConstants.java",
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraManagerCallback.java",
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraNative.java",
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraInterfaceInput.java",
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraInterfaceOutput.java",
|
||||||
|
"android/org/musicdsp/orchestra/OrchestraManager.java",
|
||||||
|
"org.musicdsp.orchestra.OrchestraConstants.javah",
|
||||||
|
"audio/orchestra/api/Android.cpp",
|
||||||
|
"audio/orchestra/api/AndroidNativeInterface.cpp"
|
||||||
|
],
|
||||||
|
"path":{
|
||||||
|
"java": [
|
||||||
|
"android"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependency": [
|
||||||
|
"SDK",
|
||||||
|
"jvm-basics",
|
||||||
|
"ejson"
|
||||||
|
],
|
||||||
|
"flag": {
|
||||||
|
"c++": "-DORCHESTRA_BUILD_JAVA"
|
||||||
|
},
|
||||||
|
"LUTIN:actions": {
|
||||||
|
"state": "BINARY",
|
||||||
|
"level": 11,
|
||||||
|
"name": "audio-orchestra-out-wrapper",
|
||||||
|
"cmd": "command_generateAddJavaSectionInClass.py",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -5,49 +5,43 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#include <etk/types.h>
|
//#include <etk/types.hpp>
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <iostream>
|
#include <etk/types.hpp>
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#undef __class__
|
|
||||||
#define __class__ "api"
|
|
||||||
|
|
||||||
// Static variable definitions.
|
// Static variable definitions.
|
||||||
const std::vector<uint32_t>& audio::orchestra::genericSampleRate() {
|
const etk::Vector<uint32_t>& audio::orchestra::genericSampleRate() {
|
||||||
static std::vector<uint32_t> list;
|
static etk::Vector<uint32_t> list;
|
||||||
if (list.size() == 0) {
|
if (list.size() == 0) {
|
||||||
list.push_back(4000);
|
list.pushBack(4000);
|
||||||
list.push_back(5512);
|
list.pushBack(5512);
|
||||||
list.push_back(8000);
|
list.pushBack(8000);
|
||||||
list.push_back(9600);
|
list.pushBack(9600);
|
||||||
list.push_back(11025);
|
list.pushBack(11025);
|
||||||
list.push_back(16000);
|
list.pushBack(16000);
|
||||||
list.push_back(22050);
|
list.pushBack(22050);
|
||||||
list.push_back(32000);
|
list.pushBack(32000);
|
||||||
list.push_back(44100);
|
list.pushBack(44100);
|
||||||
list.push_back(48000);
|
list.pushBack(48000);
|
||||||
list.push_back(64000);
|
list.pushBack(64000);
|
||||||
list.push_back(88200);
|
list.pushBack(88200);
|
||||||
list.push_back(96000);
|
list.pushBack(96000);
|
||||||
list.push_back(128000);
|
list.pushBack(128000);
|
||||||
list.push_back(176400);
|
list.pushBack(176400);
|
||||||
list.push_back(192000);
|
list.pushBack(192000);
|
||||||
list.push_back(256000);
|
list.pushBack(256000);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
audio::orchestra::Api::Api() :
|
audio::orchestra::Api::Api() :
|
||||||
m_callback(nullptr),
|
m_callback(null),
|
||||||
m_deviceBuffer(nullptr) {
|
m_deviceBuffer(null) {
|
||||||
m_device[0] = 11111;
|
m_device[0] = 11111;
|
||||||
m_device[1] = 11111;
|
m_device[1] = 11111;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,34 +52,34 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::Api::openStream(audio::orchestra::StreamParameters* _oParams,
|
enum audio::orchestra::error audio::orchestra::Api::openStream(audio::orchestra::StreamParameters* _oParams,
|
||||||
audio::orchestra::StreamParameters* _iParams,
|
audio::orchestra::StreamParameters* _iParams,
|
||||||
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) {
|
const audio::orchestra::StreamOptions& _options) {
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("a stream is already open!");
|
ATA_ERROR("a stream is already open!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if ( _oParams != nullptr
|
if ( _oParams != null
|
||||||
&& _oParams->nChannels < 1) {
|
&& _oParams->nChannels < 1) {
|
||||||
ATA_ERROR("a non-nullptr output StreamParameters structure cannot have an nChannels value less than one.");
|
ATA_ERROR("a non-null output StreamParameters structure cannot have an nChannels value less than one.");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if ( _iParams != nullptr
|
if ( _iParams != null
|
||||||
&& _iParams->nChannels < 1) {
|
&& _iParams->nChannels < 1) {
|
||||||
ATA_ERROR("a non-nullptr input StreamParameters structure cannot have an nChannels value less than one.");
|
ATA_ERROR("a non-null input StreamParameters structure cannot have an nChannels value less than one.");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if ( _oParams == nullptr
|
if ( _oParams == null
|
||||||
&& _iParams == nullptr) {
|
&& _iParams == null) {
|
||||||
ATA_ERROR("input and output StreamParameters structures are both nullptr!");
|
ATA_ERROR("input and output StreamParameters structures are both null!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if (audio::getFormatBytes(_format) == 0) {
|
if (audio::getFormatBytes(_format) == 0) {
|
||||||
@@ -94,7 +88,7 @@ enum audio::orchestra::error audio::orchestra::Api::openStream(audio::orchestra:
|
|||||||
}
|
}
|
||||||
uint32_t nDevices = getDeviceCount();
|
uint32_t nDevices = getDeviceCount();
|
||||||
uint32_t oChannels = 0;
|
uint32_t oChannels = 0;
|
||||||
if (_oParams != nullptr) {
|
if (_oParams != null) {
|
||||||
oChannels = _oParams->nChannels;
|
oChannels = _oParams->nChannels;
|
||||||
if ( _oParams->deviceId >= nDevices
|
if ( _oParams->deviceId >= nDevices
|
||||||
&& _oParams->deviceName == "") {
|
&& _oParams->deviceName == "") {
|
||||||
@@ -103,7 +97,7 @@ enum audio::orchestra::error audio::orchestra::Api::openStream(audio::orchestra:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t iChannels = 0;
|
uint32_t iChannels = 0;
|
||||||
if (_iParams != nullptr) {
|
if (_iParams != null) {
|
||||||
iChannels = _iParams->nChannels;
|
iChannels = _iParams->nChannels;
|
||||||
if ( _iParams->deviceId >= nDevices
|
if ( _iParams->deviceId >= nDevices
|
||||||
&& _iParams->deviceName == "") {
|
&& _iParams->deviceName == "") {
|
||||||
@@ -168,7 +162,7 @@ enum audio::orchestra::error audio::orchestra::Api::openStream(audio::orchestra:
|
|||||||
}
|
}
|
||||||
m_callback = _callback;
|
m_callback = _callback;
|
||||||
//_options.numberOfBuffers = m_nBuffers;
|
//_options.numberOfBuffers = m_nBuffers;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +231,7 @@ uint32_t audio::orchestra::Api::getStreamSampleRate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::Api::verifyStream() {
|
enum audio::orchestra::error audio::orchestra::Api::verifyStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("a stream is not open!");
|
ATA_ERROR("a stream is not open!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
@@ -246,15 +240,15 @@ enum audio::orchestra::error audio::orchestra::Api::verifyStream() {
|
|||||||
|
|
||||||
void audio::orchestra::Api::clearStreamInfo() {
|
void audio::orchestra::Api::clearStreamInfo() {
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
m_sampleRate = 0;
|
m_sampleRate = 0;
|
||||||
m_bufferSize = 0;
|
m_bufferSize = 0;
|
||||||
m_nBuffers = 0;
|
m_nBuffers = 0;
|
||||||
m_userFormat = audio::format_unknow;
|
m_userFormat = audio::format_unknow;
|
||||||
m_startTime = audio::Time();
|
m_startTime = audio::Time();
|
||||||
m_duration = audio::Duration(0);
|
m_duration = audio::Duration(0);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
m_callback = nullptr;
|
m_callback = null;
|
||||||
for (int32_t iii=0; iii<2; ++iii) {
|
for (int32_t iii=0; iii<2; ++iii) {
|
||||||
m_device[iii] = 11111;
|
m_device[iii] = 11111;
|
||||||
m_doConvertBuffer[iii] = false;
|
m_doConvertBuffer[iii] = false;
|
||||||
@@ -298,21 +292,21 @@ void audio::orchestra::Api::setConvertInfo(audio::orchestra::mode _mode, uint32_
|
|||||||
if (m_deviceInterleaved[idTable] == false) {
|
if (m_deviceInterleaved[idTable] == false) {
|
||||||
if (_mode == audio::orchestra::mode_input) {
|
if (_mode == audio::orchestra::mode_input) {
|
||||||
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
||||||
m_convertInfo[idTable].inOffset.push_back(kkk * m_bufferSize);
|
m_convertInfo[idTable].inOffset.pushBack(kkk * m_bufferSize);
|
||||||
m_convertInfo[idTable].outOffset.push_back(kkk);
|
m_convertInfo[idTable].outOffset.pushBack(kkk);
|
||||||
m_convertInfo[idTable].inJump = 1;
|
m_convertInfo[idTable].inJump = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
||||||
m_convertInfo[idTable].inOffset.push_back(kkk);
|
m_convertInfo[idTable].inOffset.pushBack(kkk);
|
||||||
m_convertInfo[idTable].outOffset.push_back(kkk * m_bufferSize);
|
m_convertInfo[idTable].outOffset.pushBack(kkk * m_bufferSize);
|
||||||
m_convertInfo[idTable].outJump = 1;
|
m_convertInfo[idTable].outJump = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // no (de)interleaving
|
} else { // no (de)interleaving
|
||||||
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
for (int32_t kkk=0; kkk<m_convertInfo[idTable].channels; ++kkk) {
|
||||||
m_convertInfo[idTable].inOffset.push_back(kkk);
|
m_convertInfo[idTable].inOffset.pushBack(kkk);
|
||||||
m_convertInfo[idTable].outOffset.push_back(kkk);
|
m_convertInfo[idTable].outOffset.pushBack(kkk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,33 +6,38 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <sstream>
|
#include <etk/Stream.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <audio/orchestra/type.h>
|
#include <audio/orchestra/type.hpp>
|
||||||
#include <audio/orchestra/state.h>
|
#include <audio/orchestra/state.hpp>
|
||||||
#include <audio/orchestra/mode.h>
|
#include <audio/orchestra/mode.hpp>
|
||||||
#include <audio/Time.h>
|
#include <audio/Time.hpp>
|
||||||
#include <audio/Duration.h>
|
#include <audio/Duration.hpp>
|
||||||
#include <memory>
|
#include <ememory/memory.hpp>
|
||||||
|
/**
|
||||||
|
* @brief Audio library namespace
|
||||||
|
*/
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
/**
|
||||||
|
* @brief Audio-orchestra library namespace
|
||||||
|
*/
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
const std::vector<uint32_t>& genericSampleRate();
|
const etk::Vector<uint32_t>& genericSampleRate();
|
||||||
/**
|
/**
|
||||||
* @brief airtaudio callback function prototype.
|
* @brief airtaudio callback function prototype.
|
||||||
* @param _inputBuffer For input (or duplex) streams, this buffer will hold _nbChunk of input audio chunk (nullptr if no data).
|
* @param _inputBuffer For input (or duplex) streams, this buffer will hold _nbChunk of input audio chunk (null if no data).
|
||||||
* @param _timeInput Timestamp of the first buffer sample (recording time).
|
* @param _timeInput Timestamp of the first buffer sample (recording time).
|
||||||
* @param _outputBuffer For output (or duplex) streams, the client should write _nbChunk of audio chunk into this buffer (nullptr if no data).
|
* @param _outputBuffer For output (or duplex) streams, the client should write _nbChunk of audio chunk into this buffer (null if no data).
|
||||||
* @param _timeOutput Timestamp of the first buffer sample (playing time).
|
* @param _timeOutput Timestamp of the first buffer sample (playing time).
|
||||||
* @param _nbChunk The number of chunk of input or output chunk in the buffer (same size).
|
* @param _nbChunk The number of chunk of input or output chunk in the buffer (same size).
|
||||||
* @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 std::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 std::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:
|
||||||
@@ -41,24 +46,24 @@ namespace audio {
|
|||||||
int32_t outJump;
|
int32_t outJump;
|
||||||
enum audio::format inFormat;
|
enum audio::format inFormat;
|
||||||
enum audio::format outFormat;
|
enum audio::format outFormat;
|
||||||
std::vector<int> inOffset;
|
etk::Vector<int> inOffset;
|
||||||
std::vector<int> outOffset;
|
etk::Vector<int> outOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Api : public std::enable_shared_from_this<Api>{
|
class Api : public ememory::EnableSharedFromThis<Api>{
|
||||||
protected:
|
protected:
|
||||||
std::string m_name;
|
etk::String m_name;
|
||||||
public:
|
public:
|
||||||
Api();
|
Api();
|
||||||
virtual ~Api();
|
virtual ~Api();
|
||||||
void setName(const std::string& _name) {
|
void setName(const etk::String& _name) {
|
||||||
m_name = _name;
|
m_name = _name;
|
||||||
}
|
}
|
||||||
virtual const std::string& getCurrentApi() = 0;
|
virtual const etk::String& getCurrentApi() = 0;
|
||||||
virtual uint32_t getDeviceCount() = 0;
|
virtual uint32_t getDeviceCount() = 0;
|
||||||
virtual audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device) = 0;
|
virtual audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device) = 0;
|
||||||
// TODO : Check API ...
|
// TODO : Check API ...
|
||||||
virtual bool getNamedDeviceInfo(const std::string& _deviceName, audio::orchestra::DeviceInfo& _info) {
|
virtual bool getNamedDeviceInfo(const etk::String& _deviceName, audio::orchestra::DeviceInfo& _info) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual uint32_t getDefaultInputDevice();
|
virtual uint32_t getDefaultInputDevice();
|
||||||
@@ -78,19 +83,19 @@ namespace audio {
|
|||||||
uint32_t getStreamSampleRate();
|
uint32_t getStreamSampleRate();
|
||||||
virtual audio::Time getStreamTime();
|
virtual audio::Time getStreamTime();
|
||||||
bool isStreamOpen() const {
|
bool isStreamOpen() const {
|
||||||
return m_state != audio::orchestra::state_closed;
|
return m_state != audio::orchestra::state::closed;
|
||||||
}
|
}
|
||||||
bool isStreamRunning() const {
|
bool isStreamRunning() const {
|
||||||
return m_state == audio::orchestra::state_running;
|
return m_state == audio::orchestra::state::running;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable std::mutex m_mutex;
|
mutable ethread::Mutex m_mutex;
|
||||||
audio::orchestra::AirTAudioCallback m_callback;
|
audio::orchestra::AirTAudioCallback m_callback;
|
||||||
uint32_t m_device[2]; // Playback and record, respectively.
|
uint32_t m_device[2]; // Playback and record, respectively.
|
||||||
enum audio::orchestra::mode m_mode; // audio::orchestra::mode_output, audio::orchestra::mode_input, or audio::orchestra::mode_duplex.
|
enum audio::orchestra::mode m_mode; // audio::orchestra::mode_output, audio::orchestra::mode_input, or audio::orchestra::mode_duplex.
|
||||||
enum audio::orchestra::state m_state; // STOPPED, RUNNING, or CLOSED
|
enum audio::orchestra::state m_state; // STOPPED, RUNNING, or CLOSED
|
||||||
std::vector<char> m_userBuffer[2]; // Playback and record, respectively.
|
etk::Vector<char> m_userBuffer[2]; // Playback and record, respectively.
|
||||||
char *m_deviceBuffer;
|
char *m_deviceBuffer;
|
||||||
bool m_doConvertBuffer[2]; // Playback and record, respectively.
|
bool m_doConvertBuffer[2]; // Playback and record, respectively.
|
||||||
bool m_deviceInterleaved[2]; // Playback and record, respectively.
|
bool m_deviceInterleaved[2]; // Playback and record, respectively.
|
||||||
@@ -125,7 +130,7 @@ namespace audio {
|
|||||||
enum audio::format _format,
|
enum audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
const audio::orchestra::StreamOptions& _options);
|
const audio::orchestra::StreamOptions& _options);
|
||||||
virtual bool openName(const std::string& _deviceName,
|
virtual bool openName(const etk::String& _deviceName,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
||||||
uint32_t _firstChannel,
|
uint32_t _firstChannel,
|
||||||
@@ -166,7 +171,7 @@ namespace audio {
|
|||||||
uint32_t _firstChannel);
|
uint32_t _firstChannel);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool isMasterOf(std::shared_ptr<audio::orchestra::Api> _api) {
|
virtual bool isMasterOf(ememory::SharedPtr<audio::orchestra::Api> _api) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
};
|
};
|
@@ -5,17 +5,13 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#include <etk/types.h>
|
//#include <etk/types.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <audio/orchestra/DeviceInfo.h>
|
#include <audio/orchestra/DeviceInfo.hpp>
|
||||||
#include <etk/stdTools.h>
|
#include <etk/stdTools.hpp>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#undef __class__
|
|
||||||
#define __class__ "DeviceInfo"
|
|
||||||
|
|
||||||
void audio::orchestra::DeviceInfo::display(int32_t _tabNumber) const {
|
void audio::orchestra::DeviceInfo::display(int32_t _tabNumber) const {
|
||||||
std::string space;
|
etk::String space;
|
||||||
for (int32_t iii=0; iii<_tabNumber; ++iii) {
|
for (int32_t iii=0; iii<_tabNumber; ++iii) {
|
||||||
space += " ";
|
space += " ";
|
||||||
}
|
}
|
||||||
@@ -45,7 +41,7 @@ void audio::orchestra::DeviceInfo::clear() {
|
|||||||
isDefault = false;
|
isDefault = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& audio::orchestra::operator <<(std::ostream& _os, const audio::orchestra::DeviceInfo& _obj) {
|
etk::Stream& audio::orchestra::operator <<(etk::Stream& _os, const audio::orchestra::DeviceInfo& _obj) {
|
||||||
_os << "{";
|
_os << "{";
|
||||||
if (_obj.isCorrect == false) {
|
if (_obj.isCorrect == false) {
|
||||||
_os << "NOT CORRECT INFORAMATIONS";
|
_os << "NOT CORRECT INFORAMATIONS";
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <audio/format.h>
|
#include <audio/format.hpp>
|
||||||
#include <audio/channel.h>
|
#include <audio/channel.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
@@ -18,11 +18,11 @@ namespace audio {
|
|||||||
public:
|
public:
|
||||||
bool isCorrect; //!< the information is correct (the system can return information incorect).
|
bool isCorrect; //!< the information is correct (the system can return information incorect).
|
||||||
bool input; //!< true if the device in an input; false: output.
|
bool input; //!< true if the device in an input; false: output.
|
||||||
std::string name; //!< Character string device identifier.
|
etk::String name; //!< Character string device identifier.
|
||||||
std::string desc; //!< description of the device
|
etk::String desc; //!< description of the device
|
||||||
std::vector<audio::channel> channels; //!< Channels interfaces.
|
etk::Vector<audio::channel> channels; //!< Channels interfaces.
|
||||||
std::vector<uint32_t> sampleRates; //!< Supported sample rates (queried from list of standard rates).
|
etk::Vector<uint32_t> sampleRates; //!< Supported sample rates (queried from list of standard rates).
|
||||||
std::vector<audio::format> nativeFormats; //!< Bit mask of supported data formats.
|
etk::Vector<audio::format> nativeFormats; //!< Bit mask of supported data formats.
|
||||||
bool isDefault; //! is default input/output
|
bool isDefault; //! is default input/output
|
||||||
// Default constructor.
|
// Default constructor.
|
||||||
DeviceInfo() :
|
DeviceInfo() :
|
||||||
@@ -43,7 +43,7 @@ namespace audio {
|
|||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
std::ostream& operator <<(std::ostream& _os, const audio::orchestra::DeviceInfo& _obj);
|
etk::Stream& operator <<(etk::Stream& _os, const audio::orchestra::DeviceInfo& _obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -5,5 +5,5 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/Flags.h>
|
#include <audio/orchestra/Flags.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
@@ -5,43 +5,39 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#include <etk/types.h>
|
//#include <etk/types.hpp>
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <iostream>
|
#include <audio/orchestra/api/Alsa.hpp>
|
||||||
#include <audio/orchestra/api/Alsa.h>
|
#include <audio/orchestra/api/Android.hpp>
|
||||||
#include <audio/orchestra/api/Android.h>
|
#include <audio/orchestra/api/Asio.hpp>
|
||||||
#include <audio/orchestra/api/Asio.h>
|
#include <audio/orchestra/api/Core.hpp>
|
||||||
#include <audio/orchestra/api/Core.h>
|
#include <audio/orchestra/api/CoreIos.hpp>
|
||||||
#include <audio/orchestra/api/CoreIos.h>
|
#include <audio/orchestra/api/Ds.hpp>
|
||||||
#include <audio/orchestra/api/Ds.h>
|
#include <audio/orchestra/api/Dummy.hpp>
|
||||||
#include <audio/orchestra/api/Dummy.h>
|
#include <audio/orchestra/api/Jack.hpp>
|
||||||
#include <audio/orchestra/api/Jack.h>
|
#include <audio/orchestra/api/Pulse.hpp>
|
||||||
#include <audio/orchestra/api/Pulse.h>
|
|
||||||
|
|
||||||
#undef __class__
|
etk::Vector<etk::String> audio::orchestra::Interface::getListApi() {
|
||||||
#define __class__ "Interface"
|
etk::Vector<etk::String> apis;
|
||||||
|
|
||||||
std::vector<std::string> audio::orchestra::Interface::getListApi() {
|
|
||||||
std::vector<std::string> apis;
|
|
||||||
// The order here will control the order of RtAudio's API search in
|
// The order here will control the order of RtAudio's API search in
|
||||||
// the constructor.
|
// the constructor.
|
||||||
for (size_t iii=0; iii<m_apiAvaillable.size(); ++iii) {
|
for (size_t iii=0; iii<m_apiAvaillable.size(); ++iii) {
|
||||||
apis.push_back(m_apiAvaillable[iii].first);
|
apis.pushBack(m_apiAvaillable[iii].first);
|
||||||
}
|
}
|
||||||
return apis;
|
return apis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void audio::orchestra::Interface::openApi(const std::string& _api) {
|
void audio::orchestra::Interface::openApi(const etk::String& _api) {
|
||||||
m_api.reset();
|
m_api.reset();
|
||||||
for (size_t iii=0; iii<m_apiAvaillable.size(); ++iii) {
|
for (size_t iii=0; iii<m_apiAvaillable.size(); ++iii) {
|
||||||
ATA_INFO("try open " << m_apiAvaillable[iii].first);
|
ATA_INFO("try open " << m_apiAvaillable[iii].first);
|
||||||
if (_api == m_apiAvaillable[iii].first) {
|
if (_api == m_apiAvaillable[iii].first) {
|
||||||
ATA_INFO(" ==> call it");
|
ATA_INFO(" ==> call it");
|
||||||
m_api = m_apiAvaillable[iii].second();
|
m_api = m_apiAvaillable[iii].second();
|
||||||
if (m_api != nullptr) {
|
if (m_api != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,44 +48,44 @@ void audio::orchestra::Interface::openApi(const std::string& _api) {
|
|||||||
|
|
||||||
|
|
||||||
audio::orchestra::Interface::Interface() :
|
audio::orchestra::Interface::Interface() :
|
||||||
m_api(nullptr) {
|
m_api(null) {
|
||||||
ATA_DEBUG("Add interface:");
|
ATA_DEBUG("Add interface:");
|
||||||
#if defined(ORCHESTRA_BUILD_JACK)
|
#if defined(ORCHESTRA_BUILD_JACK)
|
||||||
addInterface(audio::orchestra::type_jack, audio::orchestra::api::Jack::create);
|
addInterface(audio::orchestra::typeJack, audio::orchestra::api::Jack::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_ALSA)
|
#if defined(ORCHESTRA_BUILD_ALSA)
|
||||||
addInterface(audio::orchestra::type_alsa, audio::orchestra::api::Alsa::create);
|
addInterface(audio::orchestra::typeAlsa, audio::orchestra::api::Alsa::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_PULSE)
|
#if defined(ORCHESTRA_BUILD_PULSE)
|
||||||
addInterface(audio::orchestra::type_pulse, audio::orchestra::api::Pulse::create);
|
addInterface(audio::orchestra::typePulse, audio::orchestra::api::Pulse::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_ASIO)
|
#if defined(ORCHESTRA_BUILD_ASIO)
|
||||||
addInterface(audio::orchestra::type_asio, audio::orchestra::api::Asio::create);
|
addInterface(audio::orchestra::typeAsio, audio::orchestra::api::Asio::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_DS)
|
#if defined(ORCHESTRA_BUILD_DS)
|
||||||
addInterface(audio::orchestra::type_ds, audio::orchestra::api::Ds::create);
|
addInterface(audio::orchestra::typeDs, audio::orchestra::api::Ds::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_MACOSX_CORE)
|
#if defined(ORCHESTRA_BUILD_MACOSX_CORE)
|
||||||
addInterface(audio::orchestra::type_coreOSX, audio::orchestra::api::Core::create);
|
addInterface(audio::orchestra::typeCoreOSX, audio::orchestra::api::Core::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_IOS_CORE)
|
#if defined(ORCHESTRA_BUILD_IOS_CORE)
|
||||||
addInterface(audio::orchestra::type_coreIOS, audio::orchestra::api::CoreIos::create);
|
addInterface(audio::orchestra::typeCoreIOS, audio::orchestra::api::CoreIos::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_JAVA)
|
#if defined(ORCHESTRA_BUILD_JAVA)
|
||||||
addInterface(audio::orchestra::type_java, audio::orchestra::api::Android::create);
|
addInterface(audio::orchestra::typeJava, audio::orchestra::api::Android::create);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ORCHESTRA_BUILD_DUMMY)
|
#if defined(ORCHESTRA_BUILD_DUMMY)
|
||||||
addInterface(audio::orchestra::type_dummy, audio::orchestra::api::Dummy::create);
|
addInterface(audio::orchestra::typeDummy, audio::orchestra::api::Dummy::create);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::orchestra::Interface::addInterface(const std::string& _api, std::shared_ptr<Api> (*_callbackCreate)()) {
|
void audio::orchestra::Interface::addInterface(const etk::String& _api, ememory::SharedPtr<Api> (*_callbackCreate)()) {
|
||||||
m_apiAvaillable.push_back(std::pair<std::string, std::shared_ptr<Api> (*)()>(_api, _callbackCreate));
|
m_apiAvaillable.pushBack(etk::Pair<etk::String, ememory::SharedPtr<Api> (*)()>(_api, _callbackCreate));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::Interface::clear() {
|
enum audio::orchestra::error audio::orchestra::Interface::clear() {
|
||||||
ATA_INFO("Clear API ...");
|
ATA_INFO("Clear API ...");
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
ATA_WARNING("Interface NOT started!");
|
ATA_WARNING("Interface NOT started!");
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
@@ -97,17 +93,17 @@ enum audio::orchestra::error audio::orchestra::Interface::clear() {
|
|||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::Interface::instanciate(const std::string& _api) {
|
enum audio::orchestra::error audio::orchestra::Interface::instanciate(const etk::String& _api) {
|
||||||
ATA_INFO("Instanciate API ...");
|
ATA_INFO("Instanciate API ...");
|
||||||
if (m_api != nullptr) {
|
if (m_api != null) {
|
||||||
ATA_WARNING("Interface already started!");
|
ATA_WARNING("Interface already started!");
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
if (_api != audio::orchestra::type_undefined) {
|
if (_api != audio::orchestra::typeUndefined) {
|
||||||
ATA_INFO("API specified : " << _api);
|
ATA_INFO("API specified : " << _api);
|
||||||
// Attempt to open the specified API.
|
// Attempt to open the specified API.
|
||||||
openApi(_api);
|
openApi(_api);
|
||||||
if (m_api != nullptr) {
|
if (m_api != null) {
|
||||||
if (m_api->getDeviceCount() != 0) {
|
if (m_api->getDeviceCount() != 0) {
|
||||||
ATA_INFO(" ==> api open");
|
ATA_INFO(" ==> api open");
|
||||||
}
|
}
|
||||||
@@ -121,12 +117,12 @@ enum audio::orchestra::error audio::orchestra::Interface::instanciate(const std:
|
|||||||
ATA_INFO("Auto choice API :");
|
ATA_INFO("Auto choice API :");
|
||||||
// Iterate through the compiled APIs and return as soon as we find
|
// Iterate through the compiled APIs and return as soon as we find
|
||||||
// one with at least one device or we reach the end of the list.
|
// one with at least one device or we reach the end of the list.
|
||||||
std::vector<std::string> apis = getListApi();
|
etk::Vector<etk::String> apis = getListApi();
|
||||||
ATA_INFO(" find : " << apis.size() << " apis.");
|
ATA_INFO(" find : " << apis.size() << " apis.");
|
||||||
for (size_t iii=0; iii<apis.size(); ++iii) {
|
for (size_t iii=0; iii<apis.size(); ++iii) {
|
||||||
ATA_INFO("try open ...");
|
ATA_INFO("try open ...");
|
||||||
openApi(apis[iii]);
|
openApi(apis[iii]);
|
||||||
if(m_api == nullptr) {
|
if(m_api == null) {
|
||||||
ATA_ERROR(" ==> can not create ...");
|
ATA_ERROR(" ==> can not create ...");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -137,7 +133,7 @@ enum audio::orchestra::error audio::orchestra::Interface::instanciate(const std:
|
|||||||
ATA_INFO(" ==> Interface exist, but have no devices: " << m_api->getDeviceCount());
|
ATA_INFO(" ==> Interface exist, but have no devices: " << m_api->getDeviceCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_api != nullptr) {
|
if (m_api != null) {
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
ATA_ERROR("API NOT Supported '" << _api << "' not in " << getListApi());
|
ATA_ERROR("API NOT Supported '" << _api << "' not in " << getListApi());
|
||||||
@@ -156,7 +152,7 @@ enum audio::orchestra::error audio::orchestra::Interface::openStream(audio::orch
|
|||||||
uint32_t* _bufferFrames,
|
uint32_t* _bufferFrames,
|
||||||
audio::orchestra::AirTAudioCallback _callback,
|
audio::orchestra::AirTAudioCallback _callback,
|
||||||
const audio::orchestra::StreamOptions& _options) {
|
const audio::orchestra::StreamOptions& _options) {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::error_inputNull;
|
return audio::orchestra::error_inputNull;
|
||||||
}
|
}
|
||||||
return m_api->openStream(_outputParameters,
|
return m_api->openStream(_outputParameters,
|
||||||
@@ -169,20 +165,20 @@ enum audio::orchestra::error audio::orchestra::Interface::openStream(audio::orch
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool audio::orchestra::Interface::isMasterOf(audio::orchestra::Interface& _interface) {
|
bool audio::orchestra::Interface::isMasterOf(audio::orchestra::Interface& _interface) {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
ATA_ERROR("Current Master API is nullptr ...");
|
ATA_ERROR("Current Master API is null ...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_interface.m_api == nullptr) {
|
if (_interface.m_api == null) {
|
||||||
ATA_ERROR("Current Slave API is nullptr ...");
|
ATA_ERROR("Current Slave API is null ...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_api->getCurrentApi() != _interface.m_api->getCurrentApi()) {
|
if (m_api->getCurrentApi() != _interface.m_api->getCurrentApi()) {
|
||||||
ATA_ERROR("Can not link 2 Interface with not the same Low level type (?)");//" << _interface.m_adac->getCurrentApi() << " != " << m_adac->getCurrentApi() << ")");
|
ATA_ERROR("Can not link 2 Interface with not the same Low level type (?)");//" << _interface.m_adac->getCurrentApi() << " != " << m_adac->getCurrentApi() << ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_api->getCurrentApi() != audio::orchestra::type_alsa) {
|
if (m_api->getCurrentApi() != audio::orchestra::typeAlsa) {
|
||||||
ATA_ERROR("Link 2 device together work only if the interafec is ?");// << audio::orchestra::type_alsa << " not for " << m_api->getCurrentApi());
|
ATA_ERROR("Link 2 device together work only if the interafec is ?");// << audio::orchestra::type::alsa << " not for " << m_api->getCurrentApi());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_api->isMasterOf(_interface.m_api);
|
return m_api->isMasterOf(_interface.m_api);
|
||||||
|
@@ -6,11 +6,12 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <etk/String.hpp>
|
||||||
#include <vector>
|
#include <etk/Vector.hpp>
|
||||||
#include <audio/orchestra/base.h>
|
#include <etk/Pair.hpp>
|
||||||
#include <audio/orchestra/CallbackInfo.h>
|
#include <audio/orchestra/base.hpp>
|
||||||
#include <audio/orchestra/Api.h>
|
#include <audio/orchestra/CallbackInfo.hpp>
|
||||||
|
#include <audio/orchestra/Api.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
@@ -26,12 +27,12 @@ namespace audio {
|
|||||||
*/
|
*/
|
||||||
class Interface {
|
class Interface {
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::pair<std::string, std::shared_ptr<Api> (*)()> > m_apiAvaillable;
|
etk::Vector<etk::Pair<etk::String, ememory::SharedPtr<Api> (*)()> > m_apiAvaillable;
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<audio::orchestra::Api> m_api;
|
ememory::SharedPtr<audio::orchestra::Api> m_api;
|
||||||
public:
|
public:
|
||||||
void setName(const std::string& _name) {
|
void setName(const etk::String& _name) {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_api->setName(_name);
|
m_api->setName(_name);
|
||||||
@@ -40,13 +41,13 @@ namespace audio {
|
|||||||
* @brief Get the list of all availlable API in the system.
|
* @brief Get the list of all availlable API in the system.
|
||||||
* @return the list of all APIs
|
* @return the list of all APIs
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> getListApi();
|
etk::Vector<etk::String> getListApi();
|
||||||
/**
|
/**
|
||||||
* @brief Add an interface of the Possible List.
|
* @brief Add an interface of the Possible List.
|
||||||
* @param[in] _api Type of the interface.
|
* @param[in] _api Type of the interface.
|
||||||
* @param[in] _callbackCreate API creation callback.
|
* @param[in] _callbackCreate API creation callback.
|
||||||
*/
|
*/
|
||||||
void addInterface(const std::string& _api, std::shared_ptr<Api> (*_callbackCreate)());
|
void addInterface(const etk::String& _api, ememory::SharedPtr<Api> (*_callbackCreate)());
|
||||||
/**
|
/**
|
||||||
* @brief The class constructor.
|
* @brief The class constructor.
|
||||||
* @note the creating of the basic instance is done by Instanciate
|
* @note the creating of the basic instance is done by Instanciate
|
||||||
@@ -66,13 +67,13 @@ namespace audio {
|
|||||||
/**
|
/**
|
||||||
* @brief Create an interface instance
|
* @brief Create an interface instance
|
||||||
*/
|
*/
|
||||||
enum audio::orchestra::error instanciate(const std::string& _api = audio::orchestra::type_undefined);
|
enum audio::orchestra::error instanciate(const etk::String& _api = audio::orchestra::typeUndefined);
|
||||||
/**
|
/**
|
||||||
* @return the audio API specifier for the current instance of airtaudio.
|
* @return the audio API specifier for the current instance of airtaudio.
|
||||||
*/
|
*/
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::type_undefined;
|
return audio::orchestra::typeUndefined;
|
||||||
}
|
}
|
||||||
return m_api->getCurrentApi();
|
return m_api->getCurrentApi();
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,7 @@ namespace audio {
|
|||||||
* a system error occurs during processing, a warning will be issued.
|
* a system error occurs during processing, a warning will be issued.
|
||||||
*/
|
*/
|
||||||
uint32_t getDeviceCount() {
|
uint32_t getDeviceCount() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return m_api->getDeviceCount();
|
return m_api->getDeviceCount();
|
||||||
@@ -101,13 +102,13 @@ namespace audio {
|
|||||||
* @return An audio::orchestra::DeviceInfo structure for a specified device number.
|
* @return An audio::orchestra::DeviceInfo structure for a specified device number.
|
||||||
*/
|
*/
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device) {
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device) {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::DeviceInfo();
|
return audio::orchestra::DeviceInfo();
|
||||||
}
|
}
|
||||||
return m_api->getDeviceInfo(_device);
|
return m_api->getDeviceInfo(_device);
|
||||||
}
|
}
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(const std::string& _deviceName) {
|
audio::orchestra::DeviceInfo getDeviceInfo(const etk::String& _deviceName) {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::DeviceInfo();
|
return audio::orchestra::DeviceInfo();
|
||||||
}
|
}
|
||||||
audio::orchestra::DeviceInfo info;
|
audio::orchestra::DeviceInfo info;
|
||||||
@@ -124,7 +125,7 @@ namespace audio {
|
|||||||
* before attempting to open a stream.
|
* before attempting to open a stream.
|
||||||
*/
|
*/
|
||||||
uint32_t getDefaultOutputDevice() {
|
uint32_t getDefaultOutputDevice() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return m_api->getDefaultOutputDevice();
|
return m_api->getDefaultOutputDevice();
|
||||||
@@ -139,7 +140,7 @@ namespace audio {
|
|||||||
* before attempting to open a stream.
|
* before attempting to open a stream.
|
||||||
*/
|
*/
|
||||||
uint32_t getDefaultInputDevice() {
|
uint32_t getDefaultInputDevice() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return m_api->getDefaultInputDevice();
|
return m_api->getDefaultInputDevice();
|
||||||
@@ -154,12 +155,12 @@ namespace audio {
|
|||||||
* @param _outputParameters Specifies output stream parameters to use
|
* @param _outputParameters Specifies output stream parameters to use
|
||||||
* when opening a stream, including a device ID, number of channels,
|
* when opening a stream, including a device ID, number of channels,
|
||||||
* and starting channel number. For input-only streams, this
|
* and starting channel number. For input-only streams, this
|
||||||
* argument should be nullptr. The device ID is an index value between
|
* argument should be null. The device ID is an index value between
|
||||||
* 0 and getDeviceCount() - 1.
|
* 0 and getDeviceCount() - 1.
|
||||||
* @param _inputParameters Specifies input stream parameters to use
|
* @param _inputParameters Specifies input stream parameters to use
|
||||||
* when opening a stream, including a device ID, number of channels,
|
* when opening a stream, including a device ID, number of channels,
|
||||||
* and starting channel number. For output-only streams, this
|
* and starting channel number. For output-only streams, this
|
||||||
* argument should be nullptr. The device ID is an index value between
|
* argument should be null. The device ID is an index value between
|
||||||
* 0 and getDeviceCount() - 1.
|
* 0 and getDeviceCount() - 1.
|
||||||
* @param _format An audio::format specifying the desired sample data format.
|
* @param _format An audio::format specifying the desired sample data format.
|
||||||
* @param _sampleRate The desired sample rate (sample frames per second).
|
* @param _sampleRate The desired sample rate (sample frames per second).
|
||||||
@@ -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.
|
||||||
@@ -197,7 +198,7 @@ namespace audio {
|
|||||||
* returns (no exception is thrown).
|
* returns (no exception is thrown).
|
||||||
*/
|
*/
|
||||||
enum audio::orchestra::error closeStream() {
|
enum audio::orchestra::error closeStream() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::error_inputNull;
|
return audio::orchestra::error_inputNull;
|
||||||
}
|
}
|
||||||
return m_api->closeStream();
|
return m_api->closeStream();
|
||||||
@@ -211,7 +212,7 @@ namespace audio {
|
|||||||
* running.
|
* running.
|
||||||
*/
|
*/
|
||||||
enum audio::orchestra::error startStream() {
|
enum audio::orchestra::error startStream() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::error_inputNull;
|
return audio::orchestra::error_inputNull;
|
||||||
}
|
}
|
||||||
return m_api->startStream();
|
return m_api->startStream();
|
||||||
@@ -225,7 +226,7 @@ namespace audio {
|
|||||||
* stopped.
|
* stopped.
|
||||||
*/
|
*/
|
||||||
enum audio::orchestra::error stopStream() {
|
enum audio::orchestra::error stopStream() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::error_inputNull;
|
return audio::orchestra::error_inputNull;
|
||||||
}
|
}
|
||||||
return m_api->stopStream();
|
return m_api->stopStream();
|
||||||
@@ -238,7 +239,7 @@ namespace audio {
|
|||||||
* stopped.
|
* stopped.
|
||||||
*/
|
*/
|
||||||
enum audio::orchestra::error abortStream() {
|
enum audio::orchestra::error abortStream() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::orchestra::error_inputNull;
|
return audio::orchestra::error_inputNull;
|
||||||
}
|
}
|
||||||
return m_api->abortStream();
|
return m_api->abortStream();
|
||||||
@@ -247,7 +248,7 @@ namespace audio {
|
|||||||
* @return true if a stream is open and false if not.
|
* @return true if a stream is open and false if not.
|
||||||
*/
|
*/
|
||||||
bool isStreamOpen() const {
|
bool isStreamOpen() const {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_api->isStreamOpen();
|
return m_api->isStreamOpen();
|
||||||
@@ -256,7 +257,7 @@ namespace audio {
|
|||||||
* @return true if the stream is running and false if it is stopped or not open.
|
* @return true if the stream is running and false if it is stopped or not open.
|
||||||
*/
|
*/
|
||||||
bool isStreamRunning() const {
|
bool isStreamRunning() const {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_api->isStreamRunning();
|
return m_api->isStreamRunning();
|
||||||
@@ -266,7 +267,7 @@ namespace audio {
|
|||||||
* @return the number of elapsed seconds since the stream was started.
|
* @return the number of elapsed seconds since the stream was started.
|
||||||
*/
|
*/
|
||||||
audio::Time getStreamTime() {
|
audio::Time getStreamTime() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return audio::Time();
|
return audio::Time();
|
||||||
}
|
}
|
||||||
return m_api->getStreamTime();
|
return m_api->getStreamTime();
|
||||||
@@ -281,7 +282,7 @@ namespace audio {
|
|||||||
* @return The internal stream latency in sample frames.
|
* @return The internal stream latency in sample frames.
|
||||||
*/
|
*/
|
||||||
long getStreamLatency() {
|
long getStreamLatency() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return m_api->getStreamLatency();
|
return m_api->getStreamLatency();
|
||||||
@@ -293,14 +294,14 @@ namespace audio {
|
|||||||
* @return Returns actual sample rate in use by the stream.
|
* @return Returns actual sample rate in use by the stream.
|
||||||
*/
|
*/
|
||||||
uint32_t getStreamSampleRate() {
|
uint32_t getStreamSampleRate() {
|
||||||
if (m_api == nullptr) {
|
if (m_api == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return m_api->getStreamSampleRate();
|
return m_api->getStreamSampleRate();
|
||||||
}
|
}
|
||||||
bool isMasterOf(audio::orchestra::Interface& _interface);
|
bool isMasterOf(audio::orchestra::Interface& _interface);
|
||||||
protected:
|
protected:
|
||||||
void openApi(const std::string& _api);
|
void openApi(const etk::String& _api);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,9 +5,9 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/StreamOptions.h>
|
#include <audio/orchestra/StreamOptions.hpp>
|
||||||
#include <etk/stdTools.h>
|
#include <etk/stdTools.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
|
||||||
static const char* listValue[] = {
|
static const char* listValue[] = {
|
||||||
"hardware",
|
"hardware",
|
||||||
@@ -15,13 +15,13 @@ static const char* listValue[] = {
|
|||||||
"soft"
|
"soft"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& audio::orchestra::operator <<(std::ostream& _os, enum audio::orchestra::timestampMode _obj) {
|
etk::Stream& audio::orchestra::operator <<(etk::Stream& _os, enum audio::orchestra::timestampMode _obj) {
|
||||||
_os << listValue[_obj];
|
_os << listValue[_obj];
|
||||||
return _os;
|
return _os;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace etk {
|
namespace etk {
|
||||||
template <> bool from_string<enum audio::orchestra::timestampMode>(enum audio::orchestra::timestampMode& _variableRet, const std::string& _value) {
|
template <> bool from_string<enum audio::orchestra::timestampMode>(enum audio::orchestra::timestampMode& _variableRet, const etk::String& _value) {
|
||||||
if (_value == "hardware") {
|
if (_value == "hardware") {
|
||||||
_variableRet = audio::orchestra::timestampMode_Hardware;
|
_variableRet = audio::orchestra::timestampMode_Hardware;
|
||||||
return true;
|
return true;
|
||||||
@@ -37,7 +37,7 @@ namespace etk {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <enum audio::orchestra::timestampMode> std::string to_string(const enum audio::orchestra::timestampMode& _variable) {
|
template <enum audio::orchestra::timestampMode> etk::String toString(const enum audio::orchestra::timestampMode& _variable) {
|
||||||
return listValue[_variable];
|
return listValue[_variable];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,22 +6,23 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <audio/orchestra/Flags.h>
|
#include <audio/orchestra/Flags.hpp>
|
||||||
|
#include <etk/String.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
enum timestampMode {
|
enum timestampMode {
|
||||||
timestampMode_Hardware, //!< enable harware timestamp
|
timestampMode_Hardware, //!< enable harware timestamp
|
||||||
timestampMode_trigered, //!< get harware triger time stamp and ingrement with duration
|
timestampMode_trigered, //!< get harware triger time stamp and increment with duration
|
||||||
timestampMode_soft, //!< Simulate all timestamp.
|
timestampMode_soft, //!< Simulate all timestamp.
|
||||||
};
|
};
|
||||||
std::ostream& operator <<(std::ostream& _os, enum audio::orchestra::timestampMode _obj);
|
etk::Stream& operator <<(etk::Stream& _os, enum audio::orchestra::timestampMode _obj);
|
||||||
|
|
||||||
class StreamOptions {
|
class StreamOptions {
|
||||||
public:
|
public:
|
||||||
audio::orchestra::Flags flags; //!< A bit-mask of stream flags
|
audio::orchestra::Flags flags; //!< A bit-mask of stream flags
|
||||||
uint32_t numberOfBuffers; //!< Number of stream buffers.
|
uint32_t numberOfBuffers; //!< Number of stream buffers.
|
||||||
std::string streamName; //!< A stream name (currently used only in Jack).
|
etk::String streamName; //!< A stream name (currently used only in Jack).
|
||||||
enum timestampMode mode; //!< mode of timestamping data...
|
enum timestampMode mode; //!< mode of timestamping data...
|
||||||
// Default constructor.
|
// Default constructor.
|
||||||
StreamOptions() :
|
StreamOptions() :
|
@@ -14,7 +14,7 @@ namespace audio {
|
|||||||
class StreamParameters {
|
class StreamParameters {
|
||||||
public:
|
public:
|
||||||
int32_t deviceId; //!< Device index (-1 to getDeviceCount() - 1).
|
int32_t deviceId; //!< Device index (-1 to getDeviceCount() - 1).
|
||||||
std::string deviceName; //!< name of the device (if deviceId==-1 this must not be == "", and the oposite ...)
|
etk::String deviceName; //!< name of the device (if deviceId==-1 this must not be == "", and the oposite ...)
|
||||||
uint32_t nChannels; //!< Number of channels.
|
uint32_t nChannels; //!< Number of channels.
|
||||||
uint32_t firstChannel; //!< First channel index on device (default = 0).
|
uint32_t firstChannel; //!< First channel index on device (default = 0).
|
||||||
// Default constructor.
|
// Default constructor.
|
@@ -9,29 +9,27 @@
|
|||||||
#if defined(ORCHESTRA_BUILD_ALSA)
|
#if defined(ORCHESTRA_BUILD_ALSA)
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
|
||||||
#include <audio/orchestra/debug.h>
|
|
||||||
#include <etk/stdTools.h>
|
|
||||||
#include <ethread/tools.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <audio/orchestra/api/Alsa.h>
|
|
||||||
extern "C" {
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <poll.h>
|
|
||||||
}
|
|
||||||
#undef __class__
|
|
||||||
#define __class__ "api::Alsa"
|
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Alsa::create() {
|
#include <audio/orchestra/Interface.hpp>
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Alsa());
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
#include <etk/stdTools.hpp>
|
||||||
|
#include <ethread/tools.hpp>
|
||||||
|
#include <audio/orchestra/api/Alsa.hpp>
|
||||||
|
extern "C" {
|
||||||
|
#include <sched.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <limits.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Alsa::create() {
|
||||||
|
return ememory::SharedPtr<audio::orchestra::api::Alsa>(ETK_NEW(audio::orchestra::api::Alsa));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
@@ -41,17 +39,17 @@ 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;
|
||||||
std::thread* thread;
|
ethread::Thread* thread;
|
||||||
bool threadRunning;
|
bool threadRunning;
|
||||||
bool mmapInterface; //!< enable or disable mmap mode...
|
bool mmapInterface; //!< enable or disable mmap mode...
|
||||||
enum timestampMode timeMode; //!< the timestamp of the flow came from the harware.
|
enum timestampMode timeMode; //!< the timestamp of the flow came from the harware.
|
||||||
std::vector<snd_pcm_channel_area_t> areas;
|
etk::Vector<snd_pcm_channel_area_t> areas;
|
||||||
AlsaPrivate() :
|
AlsaPrivate() :
|
||||||
handle(nullptr),
|
handle(null),
|
||||||
runnable(false),
|
runnable(false),
|
||||||
thread(nullptr),
|
thread(null),
|
||||||
threadRunning(false),
|
threadRunning(false),
|
||||||
mmapInterface(false),
|
mmapInterface(false),
|
||||||
timeMode(timestampMode_soft) {
|
timeMode(timestampMode_soft) {
|
||||||
@@ -65,12 +63,12 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Alsa::Alsa() :
|
audio::orchestra::api::Alsa::Alsa() :
|
||||||
m_private(std::make_shared<audio::orchestra::api::AlsaPrivate>()) {
|
m_private(ememory::makeShared<audio::orchestra::api::AlsaPrivate>()) {
|
||||||
// Nothing to do here.
|
// Nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Alsa::~Alsa() {
|
audio::orchestra::api::Alsa::~Alsa() {
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +112,7 @@ nextcard:
|
|||||||
return nDevices;
|
return nDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const std::string& _deviceName, audio::orchestra::DeviceInfo& _info, int32_t _cardId, int32_t _subdevice, int32_t _localDeviceId, bool _input) {
|
bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const etk::String& _deviceName, audio::orchestra::DeviceInfo& _info, int32_t _cardId, int32_t _subdevice, int32_t _localDeviceId, bool _input) {
|
||||||
int32_t result;
|
int32_t result;
|
||||||
snd_ctl_t *chandle;
|
snd_ctl_t *chandle;
|
||||||
int32_t openMode = SND_PCM_ASYNC;
|
int32_t openMode = SND_PCM_ASYNC;
|
||||||
@@ -132,7 +130,7 @@ bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const std::string& _de
|
|||||||
stream = SND_PCM_STREAM_PLAYBACK;
|
stream = SND_PCM_STREAM_PLAYBACK;
|
||||||
}
|
}
|
||||||
snd_pcm_info_set_stream(pcminfo, stream);
|
snd_pcm_info_set_stream(pcminfo, stream);
|
||||||
std::vector<std::string> listElement = etk::split(_deviceName, ',');
|
etk::Vector<etk::String> listElement = etk::split(_deviceName, ',');
|
||||||
if (listElement.size() == 0) {
|
if (listElement.size() == 0) {
|
||||||
ATA_ERROR("can not get control interface = '" << _deviceName << "' Can not plit at ',' ...");
|
ATA_ERROR("can not get control interface = '" << _deviceName << "' Can not plit at ',' ...");
|
||||||
return false;
|
return false;
|
||||||
@@ -192,15 +190,13 @@ bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const std::string& _de
|
|||||||
}
|
}
|
||||||
ATA_DEBUG("Input channel = " << value);
|
ATA_DEBUG("Input channel = " << value);
|
||||||
for (int32_t iii=0; iii<value; ++iii) {
|
for (int32_t iii=0; iii<value; ++iii) {
|
||||||
_info.channels.push_back(audio::channel_unknow);
|
_info.channels.pushBack(audio::channel_unknow);
|
||||||
}
|
}
|
||||||
// Test our discrete set of sample rate values.
|
// Test our discrete set of sample rate values.
|
||||||
_info.sampleRates.clear();
|
_info.sampleRates.clear();
|
||||||
for (std::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.push_back(*it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_info.sampleRates.size() == 0) {
|
if (_info.sampleRates.size() == 0) {
|
||||||
@@ -213,27 +209,27 @@ bool audio::orchestra::api::Alsa::getNamedDeviceInfoLocal(const std::string& _de
|
|||||||
_info.nativeFormats.clear();
|
_info.nativeFormats.clear();
|
||||||
format = SND_PCM_FORMAT_S8;
|
format = SND_PCM_FORMAT_S8;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_int8);
|
_info.nativeFormats.pushBack(audio::format_int8);
|
||||||
}
|
}
|
||||||
format = SND_PCM_FORMAT_S16;
|
format = SND_PCM_FORMAT_S16;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_int16);
|
_info.nativeFormats.pushBack(audio::format_int16);
|
||||||
}
|
}
|
||||||
format = SND_PCM_FORMAT_S24;
|
format = SND_PCM_FORMAT_S24;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_int24);
|
_info.nativeFormats.pushBack(audio::format_int24);
|
||||||
}
|
}
|
||||||
format = SND_PCM_FORMAT_S32;
|
format = SND_PCM_FORMAT_S32;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_int32);
|
_info.nativeFormats.pushBack(audio::format_int32);
|
||||||
}
|
}
|
||||||
format = SND_PCM_FORMAT_FLOAT;
|
format = SND_PCM_FORMAT_FLOAT;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_float);
|
_info.nativeFormats.pushBack(audio::format_float);
|
||||||
}
|
}
|
||||||
format = SND_PCM_FORMAT_FLOAT64;
|
format = SND_PCM_FORMAT_FLOAT64;
|
||||||
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
if (snd_pcm_hw_params_test_format(phandle, params, format) == 0) {
|
||||||
_info.nativeFormats.push_back(audio::format_double);
|
_info.nativeFormats.pushBack(audio::format_double);
|
||||||
}
|
}
|
||||||
// Check that we have at least one supported format
|
// Check that we have at least one supported format
|
||||||
if (_info.nativeFormats.size() == 0) {
|
if (_info.nativeFormats.size() == 0) {
|
||||||
@@ -284,6 +280,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Alsa::getDeviceInfo(uint32_t
|
|||||||
ATA_WARNING("control next device, card = " << card << ", " << snd_strerror(result) << ".");
|
ATA_WARNING("control next device, card = " << card << ", " << snd_strerror(result) << ".");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ATA_WARNING(" ==> nbSubdevice = " << subdevice);
|
||||||
if (subdevice < 0) {
|
if (subdevice < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -322,7 +319,7 @@ foundDevice:
|
|||||||
snd_ctl_close(chandle);
|
snd_ctl_close(chandle);
|
||||||
// If a stream is already open, we cannot probe the stream devices.
|
// If a stream is already open, we cannot probe the stream devices.
|
||||||
// Thus, use the saved results.
|
// Thus, use the saved results.
|
||||||
if ( m_state != audio::orchestra::state_closed
|
if ( m_state != audio::orchestra::state::closed
|
||||||
&& ( m_device[0] == _device
|
&& ( m_device[0] == _device
|
||||||
|| m_device[1] == _device)) {
|
|| m_device[1] == _device)) {
|
||||||
if (_device >= m_devices.size()) {
|
if (_device >= m_devices.size()) {
|
||||||
@@ -407,7 +404,7 @@ foundDevice:
|
|||||||
return openName(name, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options);
|
return openName(name, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool audio::orchestra::api::Alsa::openName(const std::string& _deviceName,
|
bool audio::orchestra::api::Alsa::openName(const etk::String& _deviceName,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
||||||
uint32_t _firstChannel,
|
uint32_t _firstChannel,
|
||||||
@@ -677,7 +674,7 @@ bool audio::orchestra::api::Alsa::openName(const std::string& _deviceName,
|
|||||||
}
|
}
|
||||||
snd_pcm_uframes_t val;
|
snd_pcm_uframes_t val;
|
||||||
// Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.
|
// Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.
|
||||||
snd_pcm_sw_params_t *swParams = nullptr;
|
snd_pcm_sw_params_t *swParams = null;
|
||||||
snd_pcm_sw_params_alloca(&swParams);
|
snd_pcm_sw_params_alloca(&swParams);
|
||||||
snd_pcm_sw_params_current(m_private->handle, swParams);
|
snd_pcm_sw_params_current(m_private->handle, swParams);
|
||||||
#if 0
|
#if 0
|
||||||
@@ -784,10 +781,10 @@ bool audio::orchestra::api::Alsa::openName(const std::string& _deviceName,
|
|||||||
bufferBytes *= *_bufferSize;
|
bufferBytes *= *_bufferSize;
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -795,7 +792,7 @@ bool audio::orchestra::api::Alsa::openName(const std::string& _deviceName,
|
|||||||
m_nBuffers = periods;
|
m_nBuffers = periods;
|
||||||
ATA_INFO("ALSA NB buffer = " << m_nBuffers);
|
ATA_INFO("ALSA NB buffer = " << m_nBuffers);
|
||||||
// TODO : m_device[modeToIdTable(_mode)] = _device;
|
// TODO : m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
// Setup the buffer conversion information structure.
|
// Setup the buffer conversion information structure.
|
||||||
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
||||||
setConvertInfo(_mode, _firstChannel);
|
setConvertInfo(_mode, _firstChannel);
|
||||||
@@ -804,8 +801,8 @@ bool audio::orchestra::api::Alsa::openName(const std::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 std::thread(&audio::orchestra::api::Alsa::alsaCallbackEvent, this);
|
m_private->thread = ETK_NEW(ethread::Thread, [=]() {callbackEvent();});
|
||||||
if (m_private->thread == nullptr) {
|
if (m_private->thread == null) {
|
||||||
m_private->threadRunning = false;
|
m_private->threadRunning = false;
|
||||||
ATA_ERROR("creating callback thread!");
|
ATA_ERROR("creating callback thread!");
|
||||||
goto error;
|
goto error;
|
||||||
@@ -815,7 +812,7 @@ bool audio::orchestra::api::Alsa::openName(const std::string& _deviceName,
|
|||||||
error:
|
error:
|
||||||
if (m_private->handle) {
|
if (m_private->handle) {
|
||||||
snd_pcm_close(m_private->handle);
|
snd_pcm_close(m_private->handle);
|
||||||
m_private->handle = nullptr;
|
m_private->handle = null;
|
||||||
}
|
}
|
||||||
for (int32_t iii=0; iii<2; ++iii) {
|
for (int32_t iii=0; iii<2; ++iii) {
|
||||||
m_userBuffer[iii].clear();
|
m_userBuffer[iii].clear();
|
||||||
@@ -824,34 +821,34 @@ error:
|
|||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Alsa::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Alsa::closeStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("no open stream to close!");
|
ATA_ERROR("no open stream to close!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
m_private->threadRunning = false;
|
m_private->threadRunning = false;
|
||||||
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 != null) {
|
||||||
m_private->thread->join();
|
m_private->thread->join();
|
||||||
m_private->thread = nullptr;
|
m_private->thread = null;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
snd_pcm_drop(m_private->handle);
|
snd_pcm_drop(m_private->handle);
|
||||||
}
|
}
|
||||||
// close all stream :
|
// close all stream :
|
||||||
if (m_private->handle) {
|
if (m_private->handle) {
|
||||||
snd_pcm_close(m_private->handle);
|
snd_pcm_close(m_private->handle);
|
||||||
m_private->handle = nullptr;
|
m_private->handle = null;
|
||||||
}
|
}
|
||||||
for (int32_t iii=0; iii<2; ++iii) {
|
for (int32_t iii=0; iii<2; ++iii) {
|
||||||
m_userBuffer[iii].clear();
|
m_userBuffer[iii].clear();
|
||||||
@@ -861,28 +858,34 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::closeStream() {
|
|||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ATA_DEBUG("Lock");
|
||||||
|
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 == null) {
|
||||||
ATA_ERROR("send nullptr to alsa ...");
|
ATA_ERROR("send null 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);
|
||||||
@@ -891,13 +894,15 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::startStream() {
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,12 +910,12 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::stopStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
if (m_mode == audio::orchestra::mode_output) {
|
if (m_mode == audio::orchestra::mode_output) {
|
||||||
result = snd_pcm_drain(m_private->handle);
|
result = snd_pcm_drain(m_private->handle);
|
||||||
@@ -932,12 +937,12 @@ enum audio::orchestra::error audio::orchestra::api::Alsa::abortStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
result = snd_pcm_drop(m_private->handle);
|
result = snd_pcm_drop(m_private->handle);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
@@ -951,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,18 +978,17 @@ 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) {
|
||||||
std::unique_lock<std::mutex> 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ethread::setName("Alsa IO-" + m_name);
|
ethread::setName("Alsa IO-" + m_name);
|
||||||
//Wait data with poll
|
//Wait data with poll
|
||||||
std::vector<struct pollfd> ufds;
|
etk::Vector<struct pollfd> ufds;
|
||||||
signed short *ptr;
|
signed short *ptr;
|
||||||
int32_t err, count, cptr, init;
|
int32_t err, count, cptr, init;
|
||||||
count = snd_pcm_poll_descriptors_count(m_private->handle);
|
count = snd_pcm_poll_descriptors_count(m_private->handle);
|
||||||
@@ -1033,7 +1031,7 @@ void audio::orchestra::api::Alsa::callbackEvent() {
|
|||||||
audio::Time audio::orchestra::api::Alsa::getStreamTime() {
|
audio::Time audio::orchestra::api::Alsa::getStreamTime() {
|
||||||
//ATA_DEBUG("mode : " << m_private->timeMode);
|
//ATA_DEBUG("mode : " << m_private->timeMode);
|
||||||
if (m_private->timeMode == timestampMode_Hardware) {
|
if (m_private->timeMode == timestampMode_Hardware) {
|
||||||
snd_pcm_status_t *status = nullptr;
|
snd_pcm_status_t *status = null;
|
||||||
snd_pcm_status_alloca(&status);
|
snd_pcm_status_alloca(&status);
|
||||||
// get harware timestamp all the time:
|
// get harware timestamp all the time:
|
||||||
snd_pcm_status(m_private->handle, status);
|
snd_pcm_status(m_private->handle, status);
|
||||||
@@ -1056,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
|
||||||
@@ -1068,7 +1066,7 @@ audio::Time audio::orchestra::api::Alsa::getStreamTime() {
|
|||||||
return m_startTime;
|
return m_startTime;
|
||||||
} else if (m_private->timeMode == timestampMode_trigered) {
|
} else if (m_private->timeMode == timestampMode_trigered) {
|
||||||
if (m_startTime == audio::Time()) {
|
if (m_startTime == audio::Time()) {
|
||||||
snd_pcm_status_t *status = nullptr;
|
snd_pcm_status_t *status = null;
|
||||||
snd_pcm_status_alloca(&status);
|
snd_pcm_status_alloca(&status);
|
||||||
// get harware timestamp all the time:
|
// get harware timestamp all the time:
|
||||||
snd_pcm_status(m_private->handle, status);
|
snd_pcm_status(m_private->handle, status);
|
||||||
@@ -1100,15 +1098,16 @@ audio::Time audio::orchestra::api::Alsa::getStreamTime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void audio::orchestra::api::Alsa::callbackEventOneCycleRead() {
|
void audio::orchestra::api::Alsa::callbackEventOneCycleRead() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
ATA_VERBOSE("One cycle read ...");
|
||||||
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
||||||
return; // TODO : notify appl: audio::orchestra::error_warning;
|
return; // TODO : notify appl: audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime;
|
audio::Time streamTime;
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_private->xrun[0] == true) {
|
if (m_private->xrun[0] == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
int32_t result;
|
int32_t result;
|
||||||
@@ -1117,11 +1116,11 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleRead() {
|
|||||||
snd_pcm_sframes_t frames;
|
snd_pcm_sframes_t frames;
|
||||||
audio::format format;
|
audio::format format;
|
||||||
|
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
// !!! goto unlock;
|
// !!! goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
// Setup parameters.
|
// Setup parameters.
|
||||||
if (m_doConvertBuffer[1]) {
|
if (m_doConvertBuffer[1]) {
|
||||||
buffer = m_deviceBuffer;
|
buffer = m_deviceBuffer;
|
||||||
@@ -1151,7 +1150,8 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleRead() {
|
|||||||
}
|
}
|
||||||
// get timestamp : (to init here ...
|
// get timestamp : (to init here ...
|
||||||
streamTime = getStreamTime();
|
streamTime = getStreamTime();
|
||||||
if (result < (int) m_bufferSize) {
|
ATA_VERBOSE("get data :" << result << " request:" << int32_t(m_bufferSize));
|
||||||
|
if (result < int32_t(m_bufferSize)) {
|
||||||
// Either an error or overrun occured.
|
// Either an error or overrun occured.
|
||||||
if (result == -EPIPE) {
|
if (result == -EPIPE) {
|
||||||
snd_pcm_state_t state = snd_pcm_state(m_private->handle);
|
snd_pcm_state_t state = snd_pcm_state(m_private->handle);
|
||||||
@@ -1166,7 +1166,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleRead() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ATA_ERROR("audio read error, " << snd_strerror(result) << ".");
|
ATA_ERROR("audio read error, " << snd_strerror(result) << ".");
|
||||||
usleep(10000);
|
ethread::sleepMilliSeconds((10));
|
||||||
}
|
}
|
||||||
// TODO : Notify application ... audio::orchestra::error_warning;
|
// TODO : Notify application ... audio::orchestra::error_warning;
|
||||||
goto noInput;
|
goto noInput;
|
||||||
@@ -1192,7 +1192,7 @@ noInput:
|
|||||||
audio::Time startCall = audio::Time::now();
|
audio::Time startCall = audio::Time::now();
|
||||||
doStopStream = m_callback(&m_userBuffer[1][0],
|
doStopStream = m_callback(&m_userBuffer[1][0],
|
||||||
streamTime,// - audio::Duration(m_latency[1]*1000000000LL/int64_t(m_sampleRate)),
|
streamTime,// - audio::Duration(m_latency[1]*1000000000LL/int64_t(m_sampleRate)),
|
||||||
nullptr,
|
null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
@@ -1200,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) {
|
||||||
@@ -1216,15 +1216,15 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void audio::orchestra::api::Alsa::callbackEventOneCycleWrite() {
|
void audio::orchestra::api::Alsa::callbackEventOneCycleWrite() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
||||||
return; // TODO : notify appl: audio::orchestra::error_warning;
|
return; // TODO : notify appl: audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime;
|
audio::Time streamTime;
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_private->xrun[1] == true) {
|
if (m_private->xrun[1] == true) {
|
||||||
status.push_back(audio::orchestra::status_overflow);
|
status.pushBack(audio::orchestra::status::overflow);
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t result;
|
int32_t result;
|
||||||
@@ -1233,14 +1233,14 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleWrite() {
|
|||||||
snd_pcm_sframes_t frames;
|
snd_pcm_sframes_t frames;
|
||||||
audio::format format;
|
audio::format format;
|
||||||
|
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
// !!! goto unlock;
|
// !!! goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamTime = getStreamTime();
|
streamTime = getStreamTime();
|
||||||
{
|
{
|
||||||
audio::Time startCall = audio::Time::now();
|
audio::Time startCall = audio::Time::now();
|
||||||
doStopStream = m_callback(nullptr,
|
doStopStream = m_callback(null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
&m_userBuffer[0][0],
|
&m_userBuffer[0][0],
|
||||||
streamTime,// + audio::Duration(m_latency[0]*1000000000LL/int64_t(m_sampleRate)),
|
streamTime,// + audio::Duration(m_latency[0]*1000000000LL/int64_t(m_sampleRate)),
|
||||||
@@ -1250,14 +1250,14 @@ 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) {
|
||||||
abortStream();
|
abortStream();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
// Setup parameters and do buffer conversion if necessary.
|
// Setup parameters and do buffer conversion if necessary.
|
||||||
if (m_doConvertBuffer[0]) {
|
if (m_doConvertBuffer[0]) {
|
||||||
buffer = m_deviceBuffer;
|
buffer = m_deviceBuffer;
|
||||||
@@ -1318,15 +1318,15 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
||||||
return; // TODO : notify appl: audio::orchestra::error_warning;
|
return; // TODO : notify appl: audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime;
|
audio::Time streamTime;
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_private->xrun[1] == true) {
|
if (m_private->xrun[1] == true) {
|
||||||
status.push_back(audio::orchestra::status_overflow);
|
status.pushBack(audio::orchestra::status::overflow);
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t result;
|
int32_t result;
|
||||||
@@ -1335,7 +1335,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
|||||||
snd_pcm_sframes_t frames;
|
snd_pcm_sframes_t frames;
|
||||||
audio::format format;
|
audio::format format;
|
||||||
|
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
// !!! goto unlock;
|
// !!! goto unlock;
|
||||||
}
|
}
|
||||||
int32_t avail = snd_pcm_avail_update(m_private->handle);
|
int32_t avail = snd_pcm_avail_update(m_private->handle);
|
||||||
@@ -1346,7 +1346,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
|||||||
streamTime = getStreamTime();
|
streamTime = getStreamTime();
|
||||||
{
|
{
|
||||||
audio::Time startCall = audio::Time::now();
|
audio::Time startCall = audio::Time::now();
|
||||||
doStopStream = m_callback(nullptr,
|
doStopStream = m_callback(null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
&m_userBuffer[0][0],
|
&m_userBuffer[0][0],
|
||||||
streamTime,// + audio::Duration(m_latency[0]*1000000000LL/int64_t(m_sampleRate)),
|
streamTime,// + audio::Duration(m_latency[0]*1000000000LL/int64_t(m_sampleRate)),
|
||||||
@@ -1356,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) {
|
||||||
@@ -1364,7 +1364,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
// Setup parameters and do buffer conversion if necessary.
|
// Setup parameters and do buffer conversion if necessary.
|
||||||
if (m_doConvertBuffer[0]) {
|
if (m_doConvertBuffer[0]) {
|
||||||
buffer = m_deviceBuffer;
|
buffer = m_deviceBuffer;
|
||||||
@@ -1396,7 +1396,7 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPWrite() {
|
|||||||
// TODO: Understand why this does not work ...
|
// TODO: Understand why this does not work ...
|
||||||
// Write samples to device in interleaved/non-interleaved format.
|
// Write samples to device in interleaved/non-interleaved format.
|
||||||
if (m_deviceInterleaved[0]) {
|
if (m_deviceInterleaved[0]) {
|
||||||
const snd_pcm_channel_area_t* myAreas = nullptr;
|
const snd_pcm_channel_area_t* myAreas = null;
|
||||||
snd_pcm_uframes_t offset, frames;
|
snd_pcm_uframes_t offset, frames;
|
||||||
frames = m_bufferSize;
|
frames = m_bufferSize;
|
||||||
ATA_DEBUG("START");
|
ATA_DEBUG("START");
|
||||||
@@ -1451,15 +1451,16 @@ unlock:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPRead() {
|
void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPRead() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
ATA_VERBOSE("One cycle read ...");
|
||||||
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
ATA_CRITICAL("the stream is closed ... this shouldn't happen!");
|
||||||
return; // TODO : notify appl: audio::orchestra::error_warning;
|
return; // TODO : notify appl: audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime;
|
audio::Time streamTime;
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_private->xrun[0] == true) {
|
if (m_private->xrun[0] == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
int32_t result;
|
int32_t result;
|
||||||
@@ -1468,11 +1469,11 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPRead() {
|
|||||||
snd_pcm_sframes_t frames;
|
snd_pcm_sframes_t frames;
|
||||||
audio::format format;
|
audio::format format;
|
||||||
|
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
ethread::UniqueLock lck(m_mutex);
|
||||||
// Setup parameters.
|
// Setup parameters.
|
||||||
if (m_doConvertBuffer[1]) {
|
if (m_doConvertBuffer[1]) {
|
||||||
buffer = m_deviceBuffer;
|
buffer = m_deviceBuffer;
|
||||||
@@ -1500,9 +1501,11 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPRead() {
|
|||||||
ATA_ERROR("Xrun...");
|
ATA_ERROR("Xrun...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// get timestamp : (to init here ...
|
ATA_VERBOSE("get data :" << result << " request:" << int32_t(m_bufferSize));
|
||||||
streamTime = getStreamTime();
|
|
||||||
if (result < (int) m_bufferSize) {
|
if (result < (int) m_bufferSize) {
|
||||||
|
if (result<0) {
|
||||||
|
ATA_PRINT("HAVE AN ERROR " << strerror(-result));
|
||||||
|
}
|
||||||
// Either an error or overrun occured.
|
// Either an error or overrun occured.
|
||||||
if (result == -EPIPE) {
|
if (result == -EPIPE) {
|
||||||
snd_pcm_state_t state = snd_pcm_state(m_private->handle);
|
snd_pcm_state_t state = snd_pcm_state(m_private->handle);
|
||||||
@@ -1517,11 +1520,13 @@ void audio::orchestra::api::Alsa::callbackEventOneCycleMMAPRead() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ATA_ERROR("audio read error, " << snd_strerror(result) << ".");
|
ATA_ERROR("audio read error, " << snd_strerror(result) << ".");
|
||||||
usleep(10000);
|
ethread::sleepMilliSeconds((10));
|
||||||
}
|
}
|
||||||
// TODO : Notify application ... audio::orchestra::error_warning;
|
// TODO : Notify application ... audio::orchestra::error_warning;
|
||||||
goto noInput;
|
goto noInput;
|
||||||
}
|
}
|
||||||
|
// get timestamp : (to init here ...
|
||||||
|
streamTime = getStreamTime();
|
||||||
// Do byte swapping if necessary.
|
// Do byte swapping if necessary.
|
||||||
if (m_doByteSwap[1]) {
|
if (m_doByteSwap[1]) {
|
||||||
byteSwapBuffer(buffer, m_bufferSize * channels, format);
|
byteSwapBuffer(buffer, m_bufferSize * channels, format);
|
||||||
@@ -1543,7 +1548,7 @@ noInput:
|
|||||||
audio::Time startCall = audio::Time::now();
|
audio::Time startCall = audio::Time::now();
|
||||||
doStopStream = m_callback(&m_userBuffer[1][0],
|
doStopStream = m_callback(&m_userBuffer[1][0],
|
||||||
streamTime,// - audio::Duration(m_latency[1]*1000000000LL/int64_t(m_sampleRate)),
|
streamTime,// - audio::Duration(m_latency[1]*1000000000LL/int64_t(m_sampleRate)),
|
||||||
nullptr,
|
null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
@@ -1551,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) {
|
||||||
@@ -1566,25 +1571,25 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool audio::orchestra::api::Alsa::isMasterOf(std::shared_ptr<audio::orchestra::Api> _api) {
|
bool audio::orchestra::api::Alsa::isMasterOf(ememory::SharedPtr<audio::orchestra::Api> _api) {
|
||||||
std::shared_ptr<audio::orchestra::api::Alsa> slave = std::dynamic_pointer_cast<audio::orchestra::api::Alsa>(_api);
|
ememory::SharedPtr<audio::orchestra::api::Alsa> slave = ememory::dynamicPointerCast<audio::orchestra::api::Alsa>(_api);
|
||||||
if (slave == nullptr) {
|
if (slave == null) {
|
||||||
ATA_ERROR("NULL ptr API (not ALSA ...)");
|
ATA_ERROR("NULL ptr API (not ALSA ...)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
ATA_ERROR("The MASTER stream is already running! ==> can not synchronize ...");
|
ATA_ERROR("The MASTER stream is already running! ==> can not synchronize ...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (slave->m_state == audio::orchestra::state_running) {
|
if (slave->m_state == audio::orchestra::state::running) {
|
||||||
ATA_ERROR("The SLAVE stream is already running! ==> can not synchronize ...");
|
ATA_ERROR("The SLAVE stream is already running! ==> can not synchronize ...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
snd_pcm_t * master = nullptr;
|
snd_pcm_t * master = null;
|
||||||
if (m_private->handle != nullptr) {
|
if (m_private->handle != null) {
|
||||||
master = m_private->handle;
|
master = m_private->handle;
|
||||||
}
|
}
|
||||||
if (master == nullptr) {
|
if (master == null) {
|
||||||
ATA_ERROR("No ALSA handles ...");
|
ATA_ERROR("No ALSA handles ...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -14,23 +14,23 @@ namespace audio {
|
|||||||
class AlsaPrivate;
|
class AlsaPrivate;
|
||||||
class Alsa: public audio::orchestra::Api {
|
class Alsa: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Alsa();
|
Alsa();
|
||||||
virtual ~Alsa();
|
virtual ~Alsa();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_alsa;
|
return audio::orchestra::typeAlsa;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
private:
|
private:
|
||||||
bool getNamedDeviceInfoLocal(const std::string& _deviceName,
|
bool getNamedDeviceInfoLocal(const etk::String& _deviceName,
|
||||||
audio::orchestra::DeviceInfo& _info,
|
audio::orchestra::DeviceInfo& _info,
|
||||||
int32_t _cardId=-1, // Alsa card ID
|
int32_t _cardId=-1, // Alsa card ID
|
||||||
int32_t _subdevice=-1, // alsa subdevice ID
|
int32_t _subdevice=-1, // alsa subdevice ID
|
||||||
int32_t _localDeviceId=-1,// local ID of device find
|
int32_t _localDeviceId=-1,// local ID of device find
|
||||||
bool _input=false);
|
bool _input=false);
|
||||||
public:
|
public:
|
||||||
bool getNamedDeviceInfo(const std::string& _deviceName, audio::orchestra::DeviceInfo& _info) {
|
bool getNamedDeviceInfo(const etk::String& _deviceName, audio::orchestra::DeviceInfo& _info) {
|
||||||
return getNamedDeviceInfoLocal(_deviceName, _info);
|
return getNamedDeviceInfoLocal(_deviceName, _info);
|
||||||
}
|
}
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -48,10 +48,8 @@ namespace audio {
|
|||||||
void callbackEventOneCycleMMAPRead();
|
void callbackEventOneCycleMMAPRead();
|
||||||
void callbackEventOneCycleMMAPWrite();
|
void callbackEventOneCycleMMAPWrite();
|
||||||
private:
|
private:
|
||||||
static void alsaCallbackEvent(void* _userData);
|
ememory::SharedPtr<AlsaPrivate> m_private;
|
||||||
private:
|
etk::Vector<audio::orchestra::DeviceInfo> m_devices;
|
||||||
std::shared_ptr<AlsaPrivate> m_private;
|
|
||||||
std::vector<audio::orchestra::DeviceInfo> m_devices;
|
|
||||||
void saveDeviceInfo();
|
void saveDeviceInfo();
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
enum audio::orchestra::mode _mode,
|
enum audio::orchestra::mode _mode,
|
||||||
@@ -62,7 +60,7 @@ namespace audio {
|
|||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
const audio::orchestra::StreamOptions& _options);
|
const audio::orchestra::StreamOptions& _options);
|
||||||
|
|
||||||
bool openName(const std::string& _deviceName,
|
bool openName(const etk::String& _deviceName,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
||||||
uint32_t _firstChannel,
|
uint32_t _firstChannel,
|
||||||
@@ -72,7 +70,7 @@ namespace audio {
|
|||||||
const audio::orchestra::StreamOptions& _options);
|
const audio::orchestra::StreamOptions& _options);
|
||||||
virtual audio::Time getStreamTime();
|
virtual audio::Time getStreamTime();
|
||||||
public:
|
public:
|
||||||
bool isMasterOf(std::shared_ptr<audio::orchestra::Api> _api);
|
bool isMasterOf(ememory::SharedPtr<audio::orchestra::Api> _api);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,19 +8,18 @@
|
|||||||
#ifdef ORCHESTRA_BUILD_JAVA
|
#ifdef ORCHESTRA_BUILD_JAVA
|
||||||
|
|
||||||
//#include <ewol/context/Context.h>
|
//#include <ewol/context/Context.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
|
||||||
#include <audio/orchestra/debug.h>
|
|
||||||
#include <audio/orchestra/api/AndroidNativeInterface.h>
|
|
||||||
#include <audio/orchestra/api/Android.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#undef __class__
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#define __class__ "api::Android"
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
#include <audio/orchestra/api/AndroidNativeInterface.hpp>
|
||||||
|
#include <audio/orchestra/api/Android.hpp>
|
||||||
|
extern "C" {
|
||||||
|
#include <limits.h>
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<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 ... ");
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Android());
|
return ememory::SharedPtr<audio::orchestra::api::Android>(ETK_NEW(audio::orchestra::api::Android));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,15 +71,15 @@ enum audio::orchestra::error audio::orchestra::api::Android::abortStream() {
|
|||||||
|
|
||||||
void audio::orchestra::api::Android::playback(int16_t* _dst, int32_t _nbChunk) {
|
void audio::orchestra::api::Android::playback(int16_t* _dst, int32_t _nbChunk) {
|
||||||
// clear output buffer:
|
// clear output buffer:
|
||||||
if (_dst != nullptr) {
|
if (_dst != null) {
|
||||||
memset(_dst, 0, _nbChunk*audio::getFormatBytes(m_deviceFormat[modeToIdTable(m_mode)])*m_nDeviceChannels[modeToIdTable(m_mode)]);
|
memset(_dst, 0, _nbChunk*audio::getFormatBytes(m_deviceFormat[modeToIdTable(m_mode)])*m_nDeviceChannels[modeToIdTable(m_mode)]);
|
||||||
}
|
}
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_doConvertBuffer[modeToIdTable(m_mode)] == true) {
|
if (m_doConvertBuffer[modeToIdTable(m_mode)] == true) {
|
||||||
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " userbuffer size = " << m_userBuffer[audio::orchestra::mode_output].size() << "pointer=" << int64_t(&m_userBuffer[audio::orchestra::mode_output][0]));
|
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " userbuffer size = " << m_userBuffer[audio::orchestra::mode_output].size() << "pointer=" << int64_t(&m_userBuffer[audio::orchestra::mode_output][0]));
|
||||||
doStopStream = m_callback(nullptr,
|
doStopStream = m_callback(null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
&m_userBuffer[m_mode][0],
|
&m_userBuffer[m_mode][0],
|
||||||
streamTime,
|
streamTime,
|
||||||
@@ -89,7 +88,7 @@ void audio::orchestra::api::Android::playback(int16_t* _dst, int32_t _nbChunk) {
|
|||||||
convertBuffer((char*)_dst, (char*)&m_userBuffer[audio::orchestra::mode_output][0], m_convertInfo[audio::orchestra::mode_output]);
|
convertBuffer((char*)_dst, (char*)&m_userBuffer[audio::orchestra::mode_output][0], m_convertInfo[audio::orchestra::mode_output]);
|
||||||
} else {
|
} else {
|
||||||
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " pointer=" << int64_t(_dst));
|
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " pointer=" << int64_t(_dst));
|
||||||
doStopStream = m_callback(nullptr,
|
doStopStream = m_callback(null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
_dst,
|
_dst,
|
||||||
streamTime,
|
streamTime,
|
||||||
@@ -107,13 +106,13 @@ void audio::orchestra::api::Android::playback(int16_t* _dst, int32_t _nbChunk) {
|
|||||||
void audio::orchestra::api::Android::record(int16_t* _dst, int32_t _nbChunk) {
|
void audio::orchestra::api::Android::record(int16_t* _dst, int32_t _nbChunk) {
|
||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_doConvertBuffer[modeToIdTable(m_mode)] == true) {
|
if (m_doConvertBuffer[modeToIdTable(m_mode)] == true) {
|
||||||
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " userbuffer size = " << m_userBuffer[audio::orchestra::mode_output].size() << "pointer=" << int64_t(&m_userBuffer[audio::orchestra::mode_output][0]));
|
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " userbuffer size = " << m_userBuffer[audio::orchestra::mode_output].size() << "pointer=" << int64_t(&m_userBuffer[audio::orchestra::mode_output][0]));
|
||||||
convertBuffer((char*)&m_userBuffer[audio::orchestra::mode_input][0], (char*)_dst, m_convertInfo[audio::orchestra::mode_input]);
|
convertBuffer((char*)&m_userBuffer[audio::orchestra::mode_input][0], (char*)_dst, m_convertInfo[audio::orchestra::mode_input]);
|
||||||
doStopStream = m_callback(&m_userBuffer[m_mode][0],
|
doStopStream = m_callback(&m_userBuffer[m_mode][0],
|
||||||
streamTime,
|
streamTime,
|
||||||
nullptr,
|
null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
uint32_t(_nbChunk),
|
uint32_t(_nbChunk),
|
||||||
status);
|
status);
|
||||||
@@ -121,7 +120,7 @@ void audio::orchestra::api::Android::record(int16_t* _dst, int32_t _nbChunk) {
|
|||||||
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " pointer=" << int64_t(_dst));
|
ATA_VERBOSE("Need playback data " << int32_t(_nbChunk) << " pointer=" << int64_t(_dst));
|
||||||
doStopStream = m_callback(_dst,
|
doStopStream = m_callback(_dst,
|
||||||
streamTime,
|
streamTime,
|
||||||
nullptr,
|
null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
uint32_t(_nbChunk),
|
uint32_t(_nbChunk),
|
||||||
status);
|
status);
|
||||||
@@ -148,7 +147,7 @@ bool audio::orchestra::api::Android::open(uint32_t _device,
|
|||||||
m_userFormat = _format;
|
m_userFormat = _format;
|
||||||
m_nUserChannels[modeToIdTable(m_mode)] = _channels;
|
m_nUserChannels[modeToIdTable(m_mode)] = _channels;
|
||||||
|
|
||||||
m_uid = audio::orchestra::api::android::open(_device, m_mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options, std::static_pointer_cast<audio::orchestra::api::Android>(shared_from_this()));
|
m_uid = audio::orchestra::api::android::open(_device, m_mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options, ememory::staticPointerCast<audio::orchestra::api::Android>(sharedFromThis()));
|
||||||
if (m_uid < 0) {
|
if (m_uid < 0) {
|
||||||
ret = false;
|
ret = false;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -7,19 +7,19 @@
|
|||||||
|
|
||||||
#ifdef ORCHESTRA_BUILD_JAVA
|
#ifdef ORCHESTRA_BUILD_JAVA
|
||||||
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
namespace api {
|
namespace api {
|
||||||
class Android: public audio::orchestra::Api {
|
class Android: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Android();
|
Android();
|
||||||
virtual ~Android();
|
virtual ~Android();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_java;
|
return audio::orchestra::typeJava;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -39,7 +39,7 @@ namespace audio {
|
|||||||
return m_uid;
|
return m_uid;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::vector<audio::orchestra::DeviceInfo> m_devices;
|
etk::Vector<audio::orchestra::DeviceInfo> m_devices;
|
||||||
void saveDeviceInfo();
|
void saveDeviceInfo();
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
@@ -4,18 +4,20 @@
|
|||||||
* @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 <mutex>
|
#include <pthread.h>
|
||||||
#include <audio/orchestra/debug.h>
|
}
|
||||||
#include <audio/orchestra/error.h>
|
#include <ethread/Mutex.hpp>
|
||||||
#include <audio/orchestra/api/AndroidNativeInterface.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <audio/orchestra/api/Android.h>
|
#include <audio/orchestra/error.hpp>
|
||||||
|
#include <audio/orchestra/api/AndroidNativeInterface.hpp>
|
||||||
|
#include <audio/orchestra/api/Android.hpp>
|
||||||
/* include auto generated file */
|
/* include auto generated file */
|
||||||
#include <org_musicdsp_orchestra_OrchestraConstants.h>
|
#include <org_musicdsp_orchestra_OrchestraConstants.h>
|
||||||
#include <jvm-basics/jvm-basics.h>
|
#include <jvm-basics/jvm-basics.hpp>
|
||||||
#include <memory>
|
#include <ememory/memory.hpp>
|
||||||
#include <ejson/ejson.h>
|
#include <ejson/ejson.hpp>
|
||||||
|
|
||||||
class AndroidOrchestraContext {
|
class AndroidOrchestraContext {
|
||||||
public:
|
public:
|
||||||
@@ -35,19 +37,19 @@ class AndroidOrchestraContext {
|
|||||||
private:
|
private:
|
||||||
bool safeInitMethodID(jmethodID& _mid, jclass& _cls, const char* _name, const char* _sign) {
|
bool safeInitMethodID(jmethodID& _mid, jclass& _cls, const char* _name, const char* _sign) {
|
||||||
_mid = m_JavaVirtualMachinePointer->GetMethodID(_cls, _name, _sign);
|
_mid = m_JavaVirtualMachinePointer->GetMethodID(_cls, _name, _sign);
|
||||||
if(_mid == nullptr) {
|
if(_mid == null) {
|
||||||
ATA_ERROR("C->java : Can't find the method " << _name);
|
ATA_ERROR("C->java : Can't find the method " << _name);
|
||||||
/* remove access on the virtual machine : */
|
/* remove access on the virtual machine : */
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool java_attach_current_thread(int *_rstatus) {
|
bool java_attach_current_thread(int *_rstatus) {
|
||||||
ATA_DEBUG("C->java : call java");
|
ATA_DEBUG("C->java : call java");
|
||||||
if (jvm_basics::getJavaVM() == nullptr) {
|
if (jvm_basics::getJavaVM() == null) {
|
||||||
ATA_ERROR("C->java : JVM not initialised");
|
ATA_ERROR("C->java : JVM not initialised");
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*_rstatus = jvm_basics::getJavaVM()->GetEnv((void **) &m_JavaVirtualMachinePointer, JNI_VERSION_1_6);
|
*_rstatus = jvm_basics::getJavaVM()->GetEnv((void **) &m_JavaVirtualMachinePointer, JNI_VERSION_1_6);
|
||||||
@@ -55,12 +57,12 @@ class AndroidOrchestraContext {
|
|||||||
JavaVMAttachArgs lJavaVMAttachArgs;
|
JavaVMAttachArgs lJavaVMAttachArgs;
|
||||||
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
|
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
|
||||||
lJavaVMAttachArgs.name = "EwolNativeThread";
|
lJavaVMAttachArgs.name = "EwolNativeThread";
|
||||||
lJavaVMAttachArgs.group = nullptr;
|
lJavaVMAttachArgs.group = null;
|
||||||
int status = jvm_basics::getJavaVM()->AttachCurrentThread(&m_JavaVirtualMachinePointer, &lJavaVMAttachArgs);
|
int status = jvm_basics::getJavaVM()->AttachCurrentThread(&m_JavaVirtualMachinePointer, &lJavaVMAttachArgs);
|
||||||
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
|
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
|
||||||
if (status != JNI_OK) {
|
if (status != JNI_OK) {
|
||||||
ATA_ERROR("C->java : AttachCurrentThread failed : " << status);
|
ATA_ERROR("C->java : AttachCurrentThread failed : " << status);
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,13 +71,13 @@ class AndroidOrchestraContext {
|
|||||||
void java_detach_current_thread(int _status) {
|
void java_detach_current_thread(int _status) {
|
||||||
if(_status == JNI_EDETACHED) {
|
if(_status == JNI_EDETACHED) {
|
||||||
jvm_basics::getJavaVM()->DetachCurrentThread();
|
jvm_basics::getJavaVM()->DetachCurrentThread();
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AndroidOrchestraContext(JNIEnv* _env, jclass _classBase, jobject _objCallback) :
|
AndroidOrchestraContext(JNIEnv* _env, jclass _classBase, jobject _objCallback) :
|
||||||
m_JavaVirtualMachinePointer(nullptr),
|
m_JavaVirtualMachinePointer(null),
|
||||||
m_javaClassOrchestra(0),
|
m_javaClassOrchestra(0),
|
||||||
m_javaClassOrchestraCallback(0),
|
m_javaClassOrchestraCallback(0),
|
||||||
m_javaObjectOrchestraCallback(0),
|
m_javaObjectOrchestraCallback(0),
|
||||||
@@ -93,7 +95,7 @@ class AndroidOrchestraContext {
|
|||||||
ATA_DEBUG("*******************************************");
|
ATA_DEBUG("*******************************************");
|
||||||
m_JavaVirtualMachinePointer = _env;
|
m_JavaVirtualMachinePointer = _env;
|
||||||
// get default needed all time elements :
|
// get default needed all time elements :
|
||||||
if (m_JavaVirtualMachinePointer == nullptr) {
|
if (m_JavaVirtualMachinePointer == null) {
|
||||||
ATA_ERROR("C->java: NULLPTR jvm interface");
|
ATA_ERROR("C->java: NULLPTR jvm interface");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -102,15 +104,15 @@ class AndroidOrchestraContext {
|
|||||||
if (m_javaClassOrchestra == 0) {
|
if (m_javaClassOrchestra == 0) {
|
||||||
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/OrchestraNative class");
|
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/OrchestraNative class");
|
||||||
// remove access on the virtual machine :
|
// remove access on the virtual machine :
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* The object field extends Activity and implement OrchestraCallback */
|
/* The object field extends Activity and implement OrchestraCallback */
|
||||||
m_javaClassOrchestraCallback = m_JavaVirtualMachinePointer->GetObjectClass(_objCallback);
|
m_javaClassOrchestraCallback = m_JavaVirtualMachinePointer->GetObjectClass(_objCallback);
|
||||||
if(m_javaClassOrchestraCallback == nullptr) {
|
if(m_javaClassOrchestraCallback == null) {
|
||||||
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/OrchestraManagerCallback class");
|
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/OrchestraManagerCallback class");
|
||||||
// remove access on the virtual machine :
|
// remove access on the virtual machine :
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool functionCallbackIsMissing = false;
|
bool functionCallbackIsMissing = false;
|
||||||
@@ -183,7 +185,7 @@ class AndroidOrchestraContext {
|
|||||||
|
|
||||||
|
|
||||||
m_javaObjectOrchestraCallback = _env->NewGlobalRef(_objCallback);
|
m_javaObjectOrchestraCallback = _env->NewGlobalRef(_objCallback);
|
||||||
if (m_javaObjectOrchestraCallback == nullptr) {
|
if (m_javaObjectOrchestraCallback == null) {
|
||||||
functionCallbackIsMissing = true;
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ class AndroidOrchestraContext {
|
|||||||
if (m_javaDefaultClassString == 0) {
|
if (m_javaDefaultClassString == 0) {
|
||||||
ATA_ERROR("C->java : Can't find java/lang/String" );
|
ATA_ERROR("C->java : Can't find java/lang/String" );
|
||||||
// remove access on the virtual machine :
|
// remove access on the virtual machine :
|
||||||
m_JavaVirtualMachinePointer = nullptr;
|
m_JavaVirtualMachinePointer = null;
|
||||||
functionCallbackIsMissing = true;
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
if (functionCallbackIsMissing == true) {
|
if (functionCallbackIsMissing == true) {
|
||||||
@@ -205,7 +207,7 @@ class AndroidOrchestraContext {
|
|||||||
|
|
||||||
void unInit(JNIEnv* _env) {
|
void unInit(JNIEnv* _env) {
|
||||||
_env->DeleteGlobalRef(m_javaObjectOrchestraCallback);
|
_env->DeleteGlobalRef(m_javaObjectOrchestraCallback);
|
||||||
m_javaObjectOrchestraCallback = nullptr;
|
m_javaObjectOrchestraCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getDeviceCount() {
|
uint32_t getDeviceCount() {
|
||||||
@@ -234,8 +236,8 @@ class AndroidOrchestraContext {
|
|||||||
}
|
}
|
||||||
//Call java ...
|
//Call java ...
|
||||||
jstring returnString = (jstring) m_JavaVirtualMachinePointer->CallObjectMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioGetDeviceProperty, _idDevice);
|
jstring returnString = (jstring) m_JavaVirtualMachinePointer->CallObjectMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioGetDeviceProperty, _idDevice);
|
||||||
const char *js = m_JavaVirtualMachinePointer->GetStringUTFChars(returnString, nullptr);
|
const char *js = m_JavaVirtualMachinePointer->GetStringUTFChars(returnString, null);
|
||||||
std::string retString(js);
|
etk::String retString(js);
|
||||||
m_JavaVirtualMachinePointer->ReleaseStringUTFChars(returnString, js);
|
m_JavaVirtualMachinePointer->ReleaseStringUTFChars(returnString, js);
|
||||||
//m_JavaVirtualMachinePointer->DeleteLocalRef(returnString);
|
//m_JavaVirtualMachinePointer->DeleteLocalRef(returnString);
|
||||||
// manage execption :
|
// manage execption :
|
||||||
@@ -247,36 +249,36 @@ class AndroidOrchestraContext {
|
|||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
info.name = doc.getStringValue("name", "no-name");
|
info.name = doc["name"].toString().get("no-name");
|
||||||
if (doc.getStringValue("type", "output") == "output") {
|
if (doc["type"].toString().get("output") == "output") {
|
||||||
info.input = false;
|
info.input = false;
|
||||||
} else {
|
} else {
|
||||||
info.input = true;
|
info.input = true;
|
||||||
}
|
}
|
||||||
std::shared_ptr<const ejson::Array> list = doc.getArray("sample-rate");
|
ejson::Array list = doc["sample-rate"].toArray();
|
||||||
if (list != nullptr) {
|
if (list.exist() == true) {
|
||||||
for (size_t iii=0; iii<list->size(); ++iii) {
|
for (auto it : list) {
|
||||||
info.sampleRates.push_back(int32_t(list->getNumberValue(iii, 48000)));
|
info.sampleRates.pushBack(int32_t(it.toNumber().get(48000)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list = doc.getArray("channels");
|
list = doc["channels"].toArray();
|
||||||
if (list != nullptr) {
|
if (list.exist() == true) {
|
||||||
for (size_t iii=0; iii<list->size(); ++iii) {
|
for (auto it : list) {
|
||||||
info.channels.push_back(audio::getChannelFromString(list->getStringValue(iii, "???")));
|
info.channels.pushBack(audio::getChannelFromString(it.toString().get("???")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list = doc.getArray("format");
|
list = doc["format"].toArray();
|
||||||
if (list != nullptr) {
|
if (list.exist() == true) {
|
||||||
for (size_t iii=0; iii<list->size(); ++iii) {
|
for (auto it : list) {
|
||||||
info.nativeFormats.push_back(audio::getFormatFromString(list->getStringValue(iii, "???")));
|
info.nativeFormats.pushBack(audio::getFormatFromString(it.toString().get("???")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.isDefault = doc.getBooleanValue("default", false);
|
info.isDefault = doc["default"].toBoolean().get(false);
|
||||||
info.isCorrect = true;
|
info.isCorrect = true;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::vector<std::weak_ptr<audio::orchestra::api::Android> > m_instanceList; // list of connected handle ...
|
etk::Vector<ememory::WeakPtr<audio::orchestra::api::Android> > m_instanceList; // list of connected handle ...
|
||||||
//AndroidAudioCallback m_audioCallBack;
|
//AndroidAudioCallback m_audioCallBack;
|
||||||
//void* m_audioCallBackUserData;
|
//void* m_audioCallBackUserData;
|
||||||
public:
|
public:
|
||||||
@@ -288,7 +290,7 @@ class AndroidOrchestraContext {
|
|||||||
audio::format _format,
|
audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
const audio::orchestra::StreamOptions& _options,
|
const audio::orchestra::StreamOptions& _options,
|
||||||
std::shared_ptr<audio::orchestra::api::Android> _instance) {
|
ememory::SharedPtr<audio::orchestra::api::Android> _instance) {
|
||||||
ATA_DEBUG("C->java : audio open device");
|
ATA_DEBUG("C->java : audio open device");
|
||||||
int status;
|
int status;
|
||||||
if(!java_attach_current_thread(&status)) {
|
if(!java_attach_current_thread(&status)) {
|
||||||
@@ -305,7 +307,7 @@ class AndroidOrchestraContext {
|
|||||||
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
|
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
|
||||||
java_detach_current_thread(status);
|
java_detach_current_thread(status);
|
||||||
if (int32_t(ret) >= 0) {
|
if (int32_t(ret) >= 0) {
|
||||||
m_instanceList.push_back(_instance);
|
m_instanceList.pushBack(_instance);
|
||||||
return int32_t(ret);
|
return int32_t(ret);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -369,7 +371,7 @@ class AndroidOrchestraContext {
|
|||||||
auto it = m_instanceList.begin();
|
auto it = m_instanceList.begin();
|
||||||
while (it != m_instanceList.end()) {
|
while (it != m_instanceList.end()) {
|
||||||
auto elem = it->lock();
|
auto elem = it->lock();
|
||||||
if (elem == nullptr) {
|
if (elem == null) {
|
||||||
it = m_instanceList.erase(it);
|
it = m_instanceList.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -383,7 +385,7 @@ class AndroidOrchestraContext {
|
|||||||
auto it = m_instanceList.begin();
|
auto it = m_instanceList.begin();
|
||||||
while (it != m_instanceList.end()) {
|
while (it != m_instanceList.end()) {
|
||||||
auto elem = it->lock();
|
auto elem = it->lock();
|
||||||
if (elem == nullptr) {
|
if (elem == null) {
|
||||||
it = m_instanceList.erase(it);
|
it = m_instanceList.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -395,12 +397,12 @@ class AndroidOrchestraContext {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::shared_ptr<AndroidOrchestraContext> s_localContext;
|
static ememory::SharedPtr<AndroidOrchestraContext> s_localContext;
|
||||||
static int32_t s_nbContextRequested(0);
|
static int32_t s_nbContextRequested(0);
|
||||||
|
|
||||||
|
|
||||||
uint32_t audio::orchestra::api::android::getDeviceCount() {
|
uint32_t audio::orchestra::api::android::getDeviceCount() {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
ATA_ERROR("Have no Orchertra API instanciate in JAVA ...");
|
ATA_ERROR("Have no Orchertra API instanciate in JAVA ...");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -408,7 +410,7 @@ uint32_t audio::orchestra::api::android::getDeviceCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::DeviceInfo audio::orchestra::api::android::getDeviceInfo(uint32_t _device) {
|
audio::orchestra::DeviceInfo audio::orchestra::api::android::getDeviceInfo(uint32_t _device) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return audio::orchestra::DeviceInfo();
|
return audio::orchestra::DeviceInfo();
|
||||||
}
|
}
|
||||||
return s_localContext->getDeviceInfo(_device);
|
return s_localContext->getDeviceInfo(_device);
|
||||||
@@ -422,36 +424,36 @@ int32_t audio::orchestra::api::android::open(uint32_t _device,
|
|||||||
audio::format _format,
|
audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
const audio::orchestra::StreamOptions& _options,
|
const audio::orchestra::StreamOptions& _options,
|
||||||
std::shared_ptr<audio::orchestra::api::Android> _instance) {
|
ememory::SharedPtr<audio::orchestra::api::Android> _instance) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return s_localContext->open(_device, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options, _instance);
|
return s_localContext->open(_device, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options, _instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::android::closeStream(int32_t _id) {
|
enum audio::orchestra::error audio::orchestra::api::android::closeStream(int32_t _id) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
return s_localContext->closeStream(_id);
|
return s_localContext->closeStream(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::android::startStream(int32_t _id) {
|
enum audio::orchestra::error audio::orchestra::api::android::startStream(int32_t _id) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
return s_localContext->startStream(_id);
|
return s_localContext->startStream(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::android::stopStream(int32_t _id) {
|
enum audio::orchestra::error audio::orchestra::api::android::stopStream(int32_t _id) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
return s_localContext->stopStream(_id);
|
return s_localContext->stopStream(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::android::abortStream(int32_t _id) {
|
enum audio::orchestra::error audio::orchestra::api::android::abortStream(int32_t _id) {
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
return s_localContext->abortStream(_id);
|
return s_localContext->abortStream(_id);
|
||||||
@@ -461,15 +463,15 @@ extern "C" {
|
|||||||
void Java_org_musicdsp_orchestra_OrchestraNative_NNsetJavaManager(JNIEnv* _env,
|
void Java_org_musicdsp_orchestra_OrchestraNative_NNsetJavaManager(JNIEnv* _env,
|
||||||
jclass _classBase,
|
jclass _classBase,
|
||||||
jobject _objCallback) {
|
jobject _objCallback) {
|
||||||
std::unique_lock<std::mutex> lock(jvm_basics::getMutexJavaVM());
|
ethread::UniqueLock lock(jvm_basics::getMutexJavaVM());
|
||||||
ATA_INFO("*******************************************");
|
ATA_INFO("*******************************************");
|
||||||
ATA_INFO("** Creating Orchestra context **");
|
ATA_INFO("** Creating Orchestra context **");
|
||||||
ATA_INFO("*******************************************");
|
ATA_INFO("*******************************************");
|
||||||
if (s_localContext != nullptr) {
|
if (s_localContext != null) {
|
||||||
s_nbContextRequested++;
|
s_nbContextRequested++;
|
||||||
}
|
}
|
||||||
s_localContext = std::make_shared<AndroidOrchestraContext>(_env, _classBase, _objCallback);
|
s_localContext = ememory::makeShared<AndroidOrchestraContext>(_env, _classBase, _objCallback);
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
ATA_ERROR("Can not allocate the orchestra main context instance");
|
ATA_ERROR("Can not allocate the orchestra main context instance");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -477,7 +479,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_musicdsp_orchestra_OrchestraNative_NNsetJavaManagerRemove(JNIEnv* _env, jclass _cls) {
|
void Java_org_musicdsp_orchestra_OrchestraNative_NNsetJavaManagerRemove(JNIEnv* _env, jclass _cls) {
|
||||||
std::unique_lock<std::mutex> lock(jvm_basics::getMutexJavaVM());
|
ethread::UniqueLock lock(jvm_basics::getMutexJavaVM());
|
||||||
ATA_INFO("*******************************************");
|
ATA_INFO("*******************************************");
|
||||||
ATA_INFO("** remove Orchestra Pointer **");
|
ATA_INFO("** remove Orchestra Pointer **");
|
||||||
ATA_INFO("*******************************************");
|
ATA_INFO("*******************************************");
|
||||||
@@ -495,15 +497,15 @@ extern "C" {
|
|||||||
jint _id,
|
jint _id,
|
||||||
jshortArray _location,
|
jshortArray _location,
|
||||||
jint _nbChunk) {
|
jint _nbChunk) {
|
||||||
std::unique_lock<std::mutex> lock(jvm_basics::getMutexJavaVM());
|
ethread::UniqueLock lock(jvm_basics::getMutexJavaVM());
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
ATA_ERROR("Call audio with no more Low level interface");
|
ATA_ERROR("Call audio with no more Low level interface");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get the short* pointer from the Java array
|
// get the short* pointer from the Java array
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
||||||
if (dst != nullptr) {
|
if (dst != null) {
|
||||||
//ATA_INFO("Need audioData " << int32_t(_nbChunk));
|
//ATA_INFO("Need audioData " << int32_t(_nbChunk));
|
||||||
s_localContext->playback(int32_t(_id), static_cast<short*>(dst), int32_t(_nbChunk));
|
s_localContext->playback(int32_t(_id), static_cast<short*>(dst), int32_t(_nbChunk));
|
||||||
}
|
}
|
||||||
@@ -518,15 +520,15 @@ extern "C" {
|
|||||||
jint _id,
|
jint _id,
|
||||||
jshortArray _location,
|
jshortArray _location,
|
||||||
jint _nbChunk) {
|
jint _nbChunk) {
|
||||||
std::unique_lock<std::mutex> lock(jvm_basics::getMutexJavaVM());
|
ethread::UniqueLock lock(jvm_basics::getMutexJavaVM());
|
||||||
if (s_localContext == nullptr) {
|
if (s_localContext == null) {
|
||||||
ATA_ERROR("Call audio with no more Low level interface");
|
ATA_ERROR("Call audio with no more Low level interface");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get the short* pointer from the Java array
|
// get the short* pointer from the Java array
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
||||||
if (dst != nullptr) {
|
if (dst != null) {
|
||||||
//ATA_INFO("Need audioData " << int32_t(_nbChunk));
|
//ATA_INFO("Need audioData " << int32_t(_nbChunk));
|
||||||
s_localContext->record(int32_t(_id), static_cast<short*>(dst), int32_t(_nbChunk));
|
s_localContext->record(int32_t(_id), static_cast<short*>(dst), int32_t(_nbChunk));
|
||||||
}
|
}
|
||||||
|
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
#ifdef ORCHESTRA_BUILD_JAVA
|
#ifdef ORCHESTRA_BUILD_JAVA
|
||||||
|
|
||||||
#include <audio/orchestra/DeviceInfo.h>
|
#include <audio/orchestra/DeviceInfo.hpp>
|
||||||
#include <audio/orchestra/mode.h>
|
#include <audio/orchestra/mode.hpp>
|
||||||
#include <audio/orchestra/error.h>
|
#include <audio/orchestra/error.hpp>
|
||||||
#include <audio/orchestra/StreamOptions.h>
|
#include <audio/orchestra/StreamOptions.hpp>
|
||||||
#include <audio/format.h>
|
#include <audio/format.hpp>
|
||||||
#include <memory>
|
#include <ememory/memory.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
@@ -29,7 +29,7 @@ namespace audio {
|
|||||||
audio::format _format,
|
audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
const audio::orchestra::StreamOptions& _options,
|
const audio::orchestra::StreamOptions& _options,
|
||||||
std::shared_ptr<audio::orchestra::api::Android> _instance);
|
ememory::SharedPtr<audio::orchestra::api::Android> _instance);
|
||||||
enum audio::orchestra::error closeStream(int32_t _id);
|
enum audio::orchestra::error closeStream(int32_t _id);
|
||||||
enum audio::orchestra::error startStream(int32_t _id);
|
enum audio::orchestra::error startStream(int32_t _id);
|
||||||
enum audio::orchestra::error stopStream(int32_t _id);
|
enum audio::orchestra::error stopStream(int32_t _id);
|
@@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
#if defined(ORCHESTRA_BUILD_ASIO)
|
#if defined(ORCHESTRA_BUILD_ASIO)
|
||||||
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Asio::create() {
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Asio::create() {
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Asio());
|
return ememory::SharedPtr<audio::orchestra::api::Asio>(ETK_NEW(audio::orchestra::api::Asio));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -32,15 +32,13 @@ std::shared_ptr<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>
|
||||||
#undef __class__
|
}
|
||||||
#define __class__ "api::Asio"
|
|
||||||
|
|
||||||
static AsioDrivers drivers;
|
static AsioDrivers drivers;
|
||||||
static ASIOCallbacks asioCallbacks;
|
static ASIOCallbacks asioCallbacks;
|
||||||
static ASIODriverInfo driverInfo;
|
static ASIODriverInfo driverInfo;
|
||||||
@@ -73,12 +71,12 @@ static void sampleRateChanged(ASIOSampleRate _sRate);
|
|||||||
static long asioMessages(long _selector, long _value, void* _message, double* _opt);
|
static long asioMessages(long _selector, long _value, void* _message, double* _opt);
|
||||||
|
|
||||||
audio::orchestra::api::Asio::Asio() :
|
audio::orchestra::api::Asio::Asio() :
|
||||||
m_private(new audio::orchestra::api::AsioPrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::AsioPrivate)) {
|
||||||
// ASIO cannot run on a multi-threaded appartment. You can call
|
// ASIO cannot run on a multi-threaded appartment. You can call
|
||||||
// CoInitialize beforehand, but it must be for appartment threading
|
// CoInitialize beforehand, but it must be for appartment threading
|
||||||
// (in which case, CoInitilialize will return S_FALSE here).
|
// (in which case, CoInitilialize will return S_FALSE here).
|
||||||
m_coInitialized = false;
|
m_coInitialized = false;
|
||||||
HRESULT hr = CoInitialize(nullptr);
|
HRESULT hr = CoInitialize(null);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
ATA_ERROR("requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)");
|
ATA_ERROR("requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)");
|
||||||
}
|
}
|
||||||
@@ -90,7 +88,7 @@ audio::orchestra::api::Asio::Asio() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Asio::~Asio() {
|
audio::orchestra::api::Asio::~Asio() {
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
if (m_coInitialized) {
|
if (m_coInitialized) {
|
||||||
@@ -116,7 +114,7 @@ rtaudio::DeviceInfo audio::orchestra::api::Asio::getDeviceInfo(uint32_t _device)
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
// If a stream is already open, we cannot probe other devices. Thus, use the saved results.
|
// If a stream is already open, we cannot probe other devices. Thus, use the saved results.
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
if (_device >= m_devices.size()) {
|
if (_device >= m_devices.size()) {
|
||||||
ATA_ERROR("device ID was not present before stream was opened.");
|
ATA_ERROR("device ID was not present before stream was opened.");
|
||||||
return info;
|
return info;
|
||||||
@@ -157,7 +155,7 @@ rtaudio::DeviceInfo audio::orchestra::api::Asio::getDeviceInfo(uint32_t _device)
|
|||||||
for (uint32_t i=0; i<MAX_SAMPLE_RATES; i++) {
|
for (uint32_t i=0; i<MAX_SAMPLE_RATES; i++) {
|
||||||
result = ASIOCanSampleRate((ASIOSampleRate) SAMPLE_RATES[i]);
|
result = ASIOCanSampleRate((ASIOSampleRate) SAMPLE_RATES[i]);
|
||||||
if (result == ASE_OK) {
|
if (result == ASE_OK) {
|
||||||
info.sampleRates.push_back(SAMPLE_RATES[i]);
|
info.sampleRates.pushBack(SAMPLE_RATES[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Determine supported data types ... just check first channel and assume rest are the same.
|
// Determine supported data types ... just check first channel and assume rest are the same.
|
||||||
@@ -176,19 +174,19 @@ rtaudio::DeviceInfo audio::orchestra::api::Asio::getDeviceInfo(uint32_t _device)
|
|||||||
info.nativeFormats.clear();
|
info.nativeFormats.clear();
|
||||||
if ( channelInfo.type == ASIOSTInt16MSB
|
if ( channelInfo.type == ASIOSTInt16MSB
|
||||||
|| channelInfo.type == ASIOSTInt16LSB) {
|
|| channelInfo.type == ASIOSTInt16LSB) {
|
||||||
info.nativeFormats.push_back(audio::format_int16);
|
info.nativeFormats.pushBack(audio::format_int16);
|
||||||
} else if ( channelInfo.type == ASIOSTInt32MSB
|
} else if ( channelInfo.type == ASIOSTInt32MSB
|
||||||
|| channelInfo.type == ASIOSTInt32LSB) {
|
|| channelInfo.type == ASIOSTInt32LSB) {
|
||||||
info.nativeFormats.push_back(audio::format_int32);
|
info.nativeFormats.pushBack(audio::format_int32);
|
||||||
} else if ( channelInfo.type == ASIOSTFloat32MSB
|
} else if ( channelInfo.type == ASIOSTFloat32MSB
|
||||||
|| channelInfo.type == ASIOSTFloat32LSB) {
|
|| channelInfo.type == ASIOSTFloat32LSB) {
|
||||||
info.nativeFormats.push_back(audio::format_float);
|
info.nativeFormats.pushBack(audio::format_float);
|
||||||
} else if ( channelInfo.type == ASIOSTFloat64MSB
|
} else if ( channelInfo.type == ASIOSTFloat64MSB
|
||||||
|| channelInfo.type == ASIOSTFloat64LSB) {
|
|| channelInfo.type == ASIOSTFloat64LSB) {
|
||||||
info.nativeFormats.push_back(audio::format_double);
|
info.nativeFormats.pushBack(audio::format_double);
|
||||||
} else if ( channelInfo.type == ASIOSTInt24MSB
|
} else if ( channelInfo.type == ASIOSTInt24MSB
|
||||||
|| channelInfo.type == ASIOSTInt24LSB) {
|
|| channelInfo.type == ASIOSTInt24LSB) {
|
||||||
info.nativeFormats.push_back(audio::format_int24);
|
info.nativeFormats.pushBack(audio::format_int24);
|
||||||
}
|
}
|
||||||
if (info.outputChannels > 0){
|
if (info.outputChannels > 0){
|
||||||
if (getDefaultOutputDevice() == _device) {
|
if (getDefaultOutputDevice() == _device) {
|
||||||
@@ -381,10 +379,10 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
log2_of_max_size = i;
|
log2_of_max_size = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long min_delta = std::abs((long)*_bufferSize - ((long)1 << log2_of_min_size));
|
long min_delta = etk::abs((long)*_bufferSize - ((long)1 << log2_of_min_size));
|
||||||
int32_t min_delta_num = log2_of_min_size;
|
int32_t min_delta_num = log2_of_min_size;
|
||||||
for (int32_t i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
|
for (int32_t i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
|
||||||
long current_delta = std::abs((long)*_bufferSize - ((long)1 << i));
|
long current_delta = etk::abs((long)*_bufferSize - ((long)1 << i));
|
||||||
if (current_delta < min_delta) {
|
if (current_delta < min_delta) {
|
||||||
min_delta = current_delta;
|
min_delta = current_delta;
|
||||||
min_delta_num = i;
|
min_delta_num = i;
|
||||||
@@ -413,10 +411,10 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
m_deviceInterleaved[modeToIdTable(_mode)] = false;
|
m_deviceInterleaved[modeToIdTable(_mode)] = false;
|
||||||
m_private->bufferInfos = 0;
|
m_private->bufferInfos = 0;
|
||||||
// Create a manual-reset event.
|
// Create a manual-reset event.
|
||||||
m_private->condition = CreateEvent(nullptr, // no security
|
m_private->condition = CreateEvent(null, // no security
|
||||||
TRUE, // manual-reset
|
TRUE, // manual-reset
|
||||||
FALSE, // non-signaled initially
|
FALSE, // non-signaled initially
|
||||||
nullptr); // unnamed
|
null); // unnamed
|
||||||
// Create the ASIO internal buffers. Since RtAudio sets up input
|
// Create the ASIO internal buffers. Since RtAudio sets up input
|
||||||
// and output separately, we'll have to dispose of previously
|
// and output separately, we'll have to dispose of previously
|
||||||
// created output buffers for a duplex stream.
|
// created output buffers for a duplex stream.
|
||||||
@@ -424,16 +422,16 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
if ( _mode == audio::orchestra::mode_input
|
if ( _mode == audio::orchestra::mode_input
|
||||||
&& m_mode == audio::orchestra::mode_output) {
|
&& m_mode == audio::orchestra::mode_output) {
|
||||||
ASIODisposeBuffers();
|
ASIODisposeBuffers();
|
||||||
if (m_private->bufferInfos == nullptr) {
|
if (m_private->bufferInfos == null) {
|
||||||
free(m_private->bufferInfos);
|
free(m_private->bufferInfos);
|
||||||
m_private->bufferInfos = nullptr;
|
m_private->bufferInfos = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
|
// Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
|
||||||
bool buffersAllocated = false;
|
bool buffersAllocated = false;
|
||||||
uint32_t i, nChannels = m_nDeviceChannels[0] + m_nDeviceChannels[1];
|
uint32_t i, nChannels = m_nDeviceChannels[0] + m_nDeviceChannels[1];
|
||||||
m_private->bufferInfos = (ASIOBufferInfo *) malloc(nChannels * sizeof(ASIOBufferInfo));
|
m_private->bufferInfos = (ASIOBufferInfo *) malloc(nChannels * sizeof(ASIOBufferInfo));
|
||||||
if (m_private->bufferInfos == nullptr) {
|
if (m_private->bufferInfos == null) {
|
||||||
ATA_ERROR("error allocating bufferInfo memory for driver (" << driverName << ").");
|
ATA_ERROR("error allocating bufferInfo memory for driver (" << driverName << ").");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -453,7 +451,7 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
asioCallbacks.bufferSwitch = &bufferSwitch;
|
asioCallbacks.bufferSwitch = &bufferSwitch;
|
||||||
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
|
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
|
||||||
asioCallbacks.asioMessage = &asioMessages;
|
asioCallbacks.asioMessage = &asioMessages;
|
||||||
asioCallbacks.bufferSwitchTimeInfo = nullptr;
|
asioCallbacks.bufferSwitchTimeInfo = null;
|
||||||
result = ASIOCreateBuffers(m_private->bufferInfos, nChannels, m_bufferSize, &asioCallbacks);
|
result = ASIOCreateBuffers(m_private->bufferInfos, nChannels, m_bufferSize, &asioCallbacks);
|
||||||
if (result != ASE_OK) {
|
if (result != ASE_OK) {
|
||||||
ATA_ERROR("driver (" << driverName << ") error (" << getAsioErrorString(result) << ") creating buffers.");
|
ATA_ERROR("driver (" << driverName << ") error (" << getAsioErrorString(result) << ") creating buffers.");
|
||||||
@@ -473,7 +471,7 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
uint64_t bufferBytes;
|
uint64_t bufferBytes;
|
||||||
bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
||||||
m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_userBuffer[modeToIdTable(_mode)] == nullptr) {
|
if (m_userBuffer[modeToIdTable(_mode)] == null) {
|
||||||
ATA_ERROR("error allocating user buffer memory.");
|
ATA_ERROR("error allocating user buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -492,10 +490,10 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
bufferBytes *= *_bufferSize;
|
bufferBytes *= *_bufferSize;
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -503,7 +501,7 @@ bool audio::orchestra::api::Asio::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
m_sampleRate = _sampleRate;
|
m_sampleRate = _sampleRate;
|
||||||
m_device[modeToIdTable(_mode)] = _device;
|
m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
if ( _mode == audio::orchestra::mode_output
|
if ( _mode == audio::orchestra::mode_output
|
||||||
&& _mode == audio::orchestra::mode_input) {
|
&& _mode == audio::orchestra::mode_input) {
|
||||||
// We had already set up an output stream.
|
// We had already set up an output stream.
|
||||||
@@ -532,9 +530,9 @@ error:
|
|||||||
}
|
}
|
||||||
drivers.removeCurrentDriver();
|
drivers.removeCurrentDriver();
|
||||||
CloseHandle(m_private->condition);
|
CloseHandle(m_private->condition);
|
||||||
if (m_private->bufferInfos != nullptr) {
|
if (m_private->bufferInfos != null) {
|
||||||
free(m_private->bufferInfos);
|
free(m_private->bufferInfos);
|
||||||
m_private->bufferInfos = nullptr;
|
m_private->bufferInfos = null;
|
||||||
}
|
}
|
||||||
for (int32_t i=0; i<2; i++) {
|
for (int32_t i=0; i<2; i++) {
|
||||||
if (m_userBuffer[i]) {
|
if (m_userBuffer[i]) {
|
||||||
@@ -550,12 +548,12 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Asio::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Asio::closeStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("no open stream to close!");
|
ATA_ERROR("no open stream to close!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
ASIOStop();
|
ASIOStop();
|
||||||
}
|
}
|
||||||
ASIODisposeBuffers();
|
ASIODisposeBuffers();
|
||||||
@@ -575,7 +573,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::closeStream() {
|
|||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,7 +585,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::startStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -599,7 +597,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::startStream() {
|
|||||||
m_private->drainCounter = 0;
|
m_private->drainCounter = 0;
|
||||||
m_private->internalDrain = false;
|
m_private->internalDrain = false;
|
||||||
ResetEvent(m_private->condition);
|
ResetEvent(m_private->condition);
|
||||||
m_state = audio::orchestra::state_running;
|
m_state = audio::orchestra::state::running;
|
||||||
asioXRun = false;
|
asioXRun = false;
|
||||||
unlock:
|
unlock:
|
||||||
stopThreadCalled = false;
|
stopThreadCalled = false;
|
||||||
@@ -613,7 +611,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::stopStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -623,7 +621,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::stopStream() {
|
|||||||
WaitForSingleObject(m_private->condition, INFINITE); // block until signaled
|
WaitForSingleObject(m_private->condition, INFINITE); // block until signaled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
ASIOError result = ASIOStop();
|
ASIOError result = ASIOStop();
|
||||||
if (result != ASE_OK) {
|
if (result != ASE_OK) {
|
||||||
ATA_ERROR("error (" << getAsioErrorString(result) << ") stopping device.");
|
ATA_ERROR("error (" << getAsioErrorString(result) << ") stopping device.");
|
||||||
@@ -638,7 +636,7 @@ enum audio::orchestra::error audio::orchestra::api::Asio::abortStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
error(audio::orchestra::error_warning);
|
error(audio::orchestra::error_warning);
|
||||||
return;
|
return;
|
||||||
@@ -666,23 +664,23 @@ static unsigned __stdcall asioStopStream(void *_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool audio::orchestra::api::Asio::callbackEvent(long bufferIndex) {
|
bool audio::orchestra::api::Asio::callbackEvent(long bufferIndex) {
|
||||||
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) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CallbackInfo *info = (CallbackInfo *) &m_callbackInfo;
|
CallbackInfo *info = (CallbackInfo *) &m_callbackInfo;
|
||||||
// Check if we were draining the stream and signal if finished.
|
// Check if we were draining the stream and signal if finished.
|
||||||
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 == false) {
|
if (m_private->internalDrain == false) {
|
||||||
SetEvent(m_private->condition);
|
SetEvent(m_private->condition);
|
||||||
} else { // spawn a thread to stop the stream
|
} else { // spawn a thread to stop the stream
|
||||||
unsigned threadId;
|
unsigned threadId;
|
||||||
m_callbackInfo.thread = _beginthreadex(nullptr,
|
m_callbackInfo.thread = _beginthreadex(null,
|
||||||
0,
|
0,
|
||||||
&asioStopStream,
|
&asioStopStream,
|
||||||
&m_callbackInfo,
|
&m_callbackInfo,
|
||||||
@@ -695,13 +693,13 @@ bool audio::orchestra::api::Asio::callbackEvent(long bufferIndex) {
|
|||||||
// draining stream.
|
// draining stream.
|
||||||
if (m_private->drainCounter == 0) {
|
if (m_private->drainCounter == 0) {
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<enum audio::orchestra::status status;
|
etk::Vector<enum audio::orchestra::status status;
|
||||||
if (m_mode != audio::orchestra::mode_input && asioXRun == true) {
|
if (m_mode != audio::orchestra::mode_input && asioXRun == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
asioXRun = false;
|
asioXRun = false;
|
||||||
}
|
}
|
||||||
if (m_mode != audio::orchestra::mode_output && asioXRun == true) {
|
if (m_mode != audio::orchestra::mode_output && asioXRun == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow;
|
status.pushBack(audio::orchestra::status::underflow;
|
||||||
asioXRun = false;
|
asioXRun = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = info->callback(m_userBuffer[1],
|
int32_t cbReturnValue = info->callback(m_userBuffer[1],
|
||||||
@@ -711,10 +709,10 @@ bool audio::orchestra::api::Asio::callbackEvent(long bufferIndex) {
|
|||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
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;
|
||||||
unsigned threadId;
|
unsigned threadId;
|
||||||
m_callbackInfo.thread = _beginthreadex(nullptr,
|
m_callbackInfo.thread = _beginthreadex(null,
|
||||||
0,
|
0,
|
||||||
&asioStopStream,
|
&asioStopStream,
|
||||||
&m_callbackInfo,
|
&m_callbackInfo,
|
||||||
|
@@ -13,12 +13,12 @@ namespace audio {
|
|||||||
class AsioPrivate:
|
class AsioPrivate:
|
||||||
class Asio: public audio::orchestra::Api {
|
class Asio: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Asio();
|
Asio();
|
||||||
virtual ~Asio();
|
virtual ~Asio();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::WINDOWS_ASIO;
|
return audio::orchestra::typeAsio;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -33,8 +33,8 @@ namespace audio {
|
|||||||
// will most likely produce highly undesireable results!
|
// will most likely produce highly undesireable results!
|
||||||
bool callbackEvent(long _bufferIndex);
|
bool callbackEvent(long _bufferIndex);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<AsioPrivate> m_private;
|
ememory::SharedPtr<AsioPrivate> m_private;
|
||||||
std::vector<audio::orchestra::DeviceInfo> m_devices;
|
etk::Vector<audio::orchestra::DeviceInfo> m_devices;
|
||||||
void saveDeviceInfo();
|
void saveDeviceInfo();
|
||||||
bool m_coInitialized;
|
bool m_coInitialized;
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
@@ -14,19 +14,16 @@
|
|||||||
|
|
||||||
#if defined(__MACOSX_CORE__) || defined(ORCHESTRA_BUILD_MACOSX_CORE)
|
#if defined(__MACOSX_CORE__) || defined(ORCHESTRA_BUILD_MACOSX_CORE)
|
||||||
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <thread>
|
#include <ethread/Thread.hpp>
|
||||||
#include <ethread/tools.h>
|
#include <ethread/tools.hpp>
|
||||||
#include <audio/orchestra/api/Core.h>
|
#include <audio/orchestra/api/Core.hpp>
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Core::create() {
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Core::create() {
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Core());
|
return ememory::SharedPtr<audio::orchestra::api::Core>(ETK_NEW(audio::orchestra::api::Core));
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef __class__
|
|
||||||
#define __class__ "api::Core"
|
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
namespace api {
|
namespace api {
|
||||||
@@ -40,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() :
|
||||||
@@ -60,13 +57,13 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Core::Core() :
|
audio::orchestra::api::Core::Core() :
|
||||||
m_private(new audio::orchestra::api::CorePrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::CorePrivate)) {
|
||||||
#if defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
|
#if defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
|
||||||
// This is a largely undocumented but absolutely necessary
|
// This is a largely undocumented but absolutely necessary
|
||||||
// requirement starting with OS-X 10.6. If not called, queries and
|
// requirement starting with OS-X 10.6. If not called, queries and
|
||||||
// updates to various audio device properties are not handled
|
// updates to various audio device properties are not handled
|
||||||
// correctly.
|
// correctly.
|
||||||
CFRunLoopRef theRunLoop = nullptr;
|
CFRunLoopRef theRunLoop = null;
|
||||||
AudioObjectPropertyAddress property = {
|
AudioObjectPropertyAddress property = {
|
||||||
kAudioHardwarePropertyRunLoop,
|
kAudioHardwarePropertyRunLoop,
|
||||||
kAudioObjectPropertyScopeGlobal,
|
kAudioObjectPropertyScopeGlobal,
|
||||||
@@ -75,7 +72,7 @@ audio::orchestra::api::Core::Core() :
|
|||||||
OSStatus result = AudioObjectSetPropertyData(kAudioObjectSystemObject,
|
OSStatus result = AudioObjectSetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
sizeof(CFRunLoopRef),
|
sizeof(CFRunLoopRef),
|
||||||
&theRunLoop);
|
&theRunLoop);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -88,7 +85,7 @@ audio::orchestra::api::Core::~Core() {
|
|||||||
// The subclass destructor gets called before the base class
|
// The subclass destructor gets called before the base class
|
||||||
// destructor, so close an existing stream before deallocating
|
// destructor, so close an existing stream before deallocating
|
||||||
// apiDeviceId memory.
|
// apiDeviceId memory.
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +98,7 @@ uint32_t audio::orchestra::api::Core::getDeviceCount() {
|
|||||||
kAudioObjectPropertyScopeGlobal,
|
kAudioObjectPropertyScopeGlobal,
|
||||||
kAudioObjectPropertyElementMaster
|
kAudioObjectPropertyElementMaster
|
||||||
};
|
};
|
||||||
OSStatus result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &dataSize);
|
OSStatus result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, null, &dataSize);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("OS-X error getting device info!");
|
ATA_ERROR("OS-X error getting device info!");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -124,7 +121,7 @@ uint32_t audio::orchestra::api::Core::getDefaultInputDevice() {
|
|||||||
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
&id);
|
&id);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -137,7 +134,7 @@ uint32_t audio::orchestra::api::Core::getDefaultInputDevice() {
|
|||||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
(void*)&deviceList);
|
(void*)&deviceList);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -168,7 +165,7 @@ uint32_t audio::orchestra::api::Core::getDefaultOutputDevice() {
|
|||||||
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
&id);
|
&id);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -181,7 +178,7 @@ uint32_t audio::orchestra::api::Core::getDefaultOutputDevice() {
|
|||||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
(void*)&deviceList);
|
(void*)&deviceList);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -226,7 +223,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
(void*)&deviceList);
|
(void*)&deviceList);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -242,7 +239,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
CFStringRef cfname;
|
CFStringRef cfname;
|
||||||
dataSize = sizeof(CFStringRef);
|
dataSize = sizeof(CFStringRef);
|
||||||
property.mSelector = kAudioObjectPropertyManufacturer;
|
property.mSelector = kAudioObjectPropertyManufacturer;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &cfname);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &cfname);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device manufacturer.");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device manufacturer.");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -250,14 +247,14 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
}
|
}
|
||||||
//const char *mname = CFStringGetCStringPtr(cfname, CFStringGetSystemEncoding());
|
//const char *mname = CFStringGetCStringPtr(cfname, CFStringGetSystemEncoding());
|
||||||
int32_t length = CFStringGetLength(cfname);
|
int32_t length = CFStringGetLength(cfname);
|
||||||
std::vector<char> name;
|
etk::Vector<char> name;
|
||||||
name.resize(length * 3 + 1, '\0');
|
name.resize(length * 3 + 1, '\0');
|
||||||
CFStringGetCString(cfname, &name[0], length * 3 + 1, CFStringGetSystemEncoding());
|
CFStringGetCString(cfname, &name[0], length * 3 + 1, CFStringGetSystemEncoding());
|
||||||
info.name.append(&name[0], strlen(&name[0]));
|
info.name.append(&name[0], strlen(&name[0]));
|
||||||
info.name.append(": ");
|
info.name.append(": ");
|
||||||
CFRelease(cfname);
|
CFRelease(cfname);
|
||||||
property.mSelector = kAudioObjectPropertyName;
|
property.mSelector = kAudioObjectPropertyName;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &cfname);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &cfname);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device name.");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device name.");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -279,9 +276,9 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
} else {
|
} else {
|
||||||
property.mScope = kAudioDevicePropertyScopeInput;
|
property.mScope = kAudioDevicePropertyScopeInput;
|
||||||
}
|
}
|
||||||
AudioBufferList *bufferList = nullptr;
|
AudioBufferList *bufferList = null;
|
||||||
dataSize = 0;
|
dataSize = 0;
|
||||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
result = AudioObjectGetPropertyDataSize(id, &property, 0, null, &dataSize);
|
||||||
if (result != noErr || dataSize == 0) {
|
if (result != noErr || dataSize == 0) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -289,12 +286,12 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
}
|
}
|
||||||
// Allocate the AudioBufferList.
|
// Allocate the AudioBufferList.
|
||||||
bufferList = (AudioBufferList *) malloc(dataSize);
|
bufferList = (AudioBufferList *) malloc(dataSize);
|
||||||
if (bufferList == nullptr) {
|
if (bufferList == null) {
|
||||||
ATA_ERROR("memory error allocating AudioBufferList.");
|
ATA_ERROR("memory error allocating AudioBufferList.");
|
||||||
info.clear();
|
info.clear();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, bufferList);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, bufferList);
|
||||||
if ( result != noErr
|
if ( result != noErr
|
||||||
|| dataSize == 0) {
|
|| dataSize == 0) {
|
||||||
free(bufferList);
|
free(bufferList);
|
||||||
@@ -305,7 +302,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
// Get channel information.
|
// Get channel information.
|
||||||
for (size_t iii=0; iii<bufferList->mNumberBuffers; ++iii) {
|
for (size_t iii=0; iii<bufferList->mNumberBuffers; ++iii) {
|
||||||
for (size_t jjj=0; jjj<bufferList->mBuffers[iii].mNumberChannels; ++jjj) {
|
for (size_t jjj=0; jjj<bufferList->mBuffers[iii].mNumberChannels; ++jjj) {
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(bufferList);
|
free(bufferList);
|
||||||
@@ -319,7 +316,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
// Determine the supported sample rates.
|
// Determine the supported sample rates.
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
||||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
result = AudioObjectGetPropertyDataSize(id, &property, 0, null, &dataSize);
|
||||||
if ( result != kAudioHardwareNoError
|
if ( result != kAudioHardwareNoError
|
||||||
|| dataSize == 0) {
|
|| dataSize == 0) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rate info.");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rate info.");
|
||||||
@@ -328,7 +325,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
}
|
}
|
||||||
uint32_t nRanges = dataSize / sizeof(AudioValueRange);
|
uint32_t nRanges = dataSize / sizeof(AudioValueRange);
|
||||||
AudioValueRange rangeList[ nRanges ];
|
AudioValueRange rangeList[ nRanges ];
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &rangeList);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &rangeList);
|
||||||
if (result != kAudioHardwareNoError) {
|
if (result != kAudioHardwareNoError) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rates.");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rates.");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -347,7 +344,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
for (auto &it : audio::orchestra::genericSampleRate()) {
|
for (auto &it : audio::orchestra::genericSampleRate()) {
|
||||||
if ( it >= minimumRate
|
if ( it >= minimumRate
|
||||||
&& it <= maximumRate) {
|
&& it <= maximumRate) {
|
||||||
info.sampleRates.push_back(it);
|
info.sampleRates.pushBack(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.sampleRates.size() == 0) {
|
if (info.sampleRates.size() == 0) {
|
||||||
@@ -361,7 +358,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
|||||||
// CoreAudio always uses 32-bit floating point data for PCM streams.
|
// CoreAudio always uses 32-bit floating point data for PCM streams.
|
||||||
// Thus, any other "physical" formats supported by the device are of
|
// Thus, any other "physical" formats supported by the device are of
|
||||||
// no interest to the client.
|
// no interest to the client.
|
||||||
info.nativeFormats.push_back(audio::format_float);
|
info.nativeFormats.pushBack(audio::format_float);
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
// Determine the default channel.
|
// Determine the default channel.
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
@@ -389,10 +386,10 @@ OSStatus audio::orchestra::api::Core::callbackEvent(AudioDeviceID _inDevice,
|
|||||||
audio::orchestra::api::Core* myClass = reinterpret_cast<audio::orchestra::api::Core*>(_userData);
|
audio::orchestra::api::Core* myClass = reinterpret_cast<audio::orchestra::api::Core*>(_userData);
|
||||||
audio::Time inputTime;
|
audio::Time inputTime;
|
||||||
audio::Time outputTime;
|
audio::Time outputTime;
|
||||||
if (_inInputTime != nullptr) {
|
if (_inInputTime != null) {
|
||||||
inputTime = audio::Time(_inInputTime->mHostTime/1000000000LL, _inInputTime->mHostTime%1000000000LL);
|
inputTime = audio::Time(_inInputTime->mHostTime/1000000000LL, _inInputTime->mHostTime%1000000000LL);
|
||||||
}
|
}
|
||||||
if (_inOutputTime != nullptr) {
|
if (_inOutputTime != null) {
|
||||||
outputTime = audio::Time(_inOutputTime->mHostTime/1000000000LL, _inOutputTime->mHostTime%1000000000LL);
|
outputTime = audio::Time(_inOutputTime->mHostTime/1000000000LL, _inOutputTime->mHostTime%1000000000LL);
|
||||||
}
|
}
|
||||||
if (myClass->callbackEvent(_inDevice, _inInputData, inputTime, _outOutputData, outputTime) == false) {
|
if (myClass->callbackEvent(_inDevice, _inInputData, inputTime, _outOutputData, outputTime) == false) {
|
||||||
@@ -430,7 +427,7 @@ static OSStatus rateListener(AudioObjectID _inDevice,
|
|||||||
kAudioObjectPropertyScopeGlobal,
|
kAudioObjectPropertyScopeGlobal,
|
||||||
kAudioObjectPropertyElementMaster
|
kAudioObjectPropertyElementMaster
|
||||||
};
|
};
|
||||||
AudioObjectGetPropertyData(_inDevice, &property, 0, nullptr, &dataSize, rate);
|
AudioObjectGetPropertyData(_inDevice, &property, 0, null, &dataSize, rate);
|
||||||
return kAudioHardwareNoError;
|
return kAudioHardwareNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +461,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&property,
|
&property,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
null,
|
||||||
&dataSize,
|
&dataSize,
|
||||||
(void *) &deviceList);
|
(void *) &deviceList);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
@@ -484,7 +481,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
AudioBufferList *bufferList = nil;
|
AudioBufferList *bufferList = nil;
|
||||||
dataSize = 0;
|
dataSize = 0;
|
||||||
property.mSelector = kAudioDevicePropertyStreamConfiguration;
|
property.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
result = AudioObjectGetPropertyDataSize(id, &property, 0, null, &dataSize);
|
||||||
if ( result != noErr
|
if ( result != noErr
|
||||||
|| dataSize == 0) {
|
|| dataSize == 0) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
|
||||||
@@ -492,11 +489,11 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Allocate the AudioBufferList.
|
// Allocate the AudioBufferList.
|
||||||
bufferList = (AudioBufferList *) malloc(dataSize);
|
bufferList = (AudioBufferList *) malloc(dataSize);
|
||||||
if (bufferList == nullptr) {
|
if (bufferList == null) {
|
||||||
ATA_ERROR("memory error allocating AudioBufferList.");
|
ATA_ERROR("memory error allocating AudioBufferList.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, bufferList);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, bufferList);
|
||||||
if ( result != noErr
|
if ( result != noErr
|
||||||
|| dataSize == 0) {
|
|| dataSize == 0) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration for device (" << _device << ").");
|
||||||
@@ -572,7 +569,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
AudioValueRange bufferRange;
|
AudioValueRange bufferRange;
|
||||||
dataSize = sizeof(AudioValueRange);
|
dataSize = sizeof(AudioValueRange);
|
||||||
property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
|
property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &bufferRange);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &bufferRange);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting buffer size range for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting buffer size range for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@@ -590,7 +587,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
uint32_t theSize = (uint32_t) *_bufferSize;
|
uint32_t theSize = (uint32_t) *_bufferSize;
|
||||||
dataSize = sizeof(uint32_t);
|
dataSize = sizeof(uint32_t);
|
||||||
property.mSelector = kAudioDevicePropertyBufferFrameSize;
|
property.mSelector = kAudioDevicePropertyBufferFrameSize;
|
||||||
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &theSize);
|
result = AudioObjectSetPropertyData(id, &property, 0, null, dataSize, &theSize);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") setting the buffer size for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") setting the buffer size for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@@ -610,7 +607,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
double nominalRate;
|
double nominalRate;
|
||||||
dataSize = sizeof(double);
|
dataSize = sizeof(double);
|
||||||
property.mSelector = kAudioDevicePropertyNominalSampleRate;
|
property.mSelector = kAudioDevicePropertyNominalSampleRate;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &nominalRate);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &nominalRate);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting current sample rate.");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting current sample rate.");
|
||||||
return false;
|
return false;
|
||||||
@@ -626,7 +623,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
nominalRate = (double) _sampleRate;
|
nominalRate = (double) _sampleRate;
|
||||||
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &nominalRate);
|
result = AudioObjectSetPropertyData(id, &property, 0, null, dataSize, &nominalRate);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@@ -638,7 +635,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
if (microCounter > 5000000) {
|
if (microCounter > 5000000) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
usleep(5000);
|
ethread::sleepMilliSeconds((5));
|
||||||
}
|
}
|
||||||
// Remove the property listener.
|
// Remove the property listener.
|
||||||
AudioObjectRemovePropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
|
AudioObjectRemovePropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
|
||||||
@@ -652,7 +649,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
AudioStreamBasicDescription description;
|
AudioStreamBasicDescription description;
|
||||||
dataSize = sizeof(AudioStreamBasicDescription);
|
dataSize = sizeof(AudioStreamBasicDescription);
|
||||||
property.mSelector = kAudioStreamPropertyVirtualFormat;
|
property.mSelector = kAudioStreamPropertyVirtualFormat;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &description);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &description);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream format for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream format for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@@ -670,7 +667,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
updateFormat = true;
|
updateFormat = true;
|
||||||
}
|
}
|
||||||
if (updateFormat) {
|
if (updateFormat) {
|
||||||
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &description);
|
result = AudioObjectSetPropertyData(id, &property, 0, null, dataSize, &description);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate or data format for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate or data format for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@@ -678,16 +675,16 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Now check the physical format.
|
// Now check the physical format.
|
||||||
property.mSelector = kAudioStreamPropertyPhysicalFormat;
|
property.mSelector = kAudioStreamPropertyPhysicalFormat;
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &description);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &description);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
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;
|
||||||
@@ -695,19 +692,19 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
AudioStreamBasicDescription testDescription = description;
|
AudioStreamBasicDescription testDescription = description;
|
||||||
uint32_t formatFlags;
|
uint32_t formatFlags;
|
||||||
// We'll try higher bit rates first and then work our way down.
|
// We'll try higher bit rates first and then work our way down.
|
||||||
std::vector< std::pair<uint32_t, uint32_t> > physicalFormats;
|
etk::Vector< etk::Pair<uint32_t, uint32_t> > physicalFormats;
|
||||||
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;
|
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(32, formatFlags));
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(32, formatFlags));
|
||||||
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
|
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(32, formatFlags));
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(32, formatFlags));
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(24, formatFlags)); // 24-bit packed
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(24, formatFlags)); // 24-bit packed
|
||||||
formatFlags &= ~(kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh);
|
formatFlags &= ~(kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh);
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(24.2, formatFlags)); // 24-bit in 4 bytes, aligned low
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(24.2, formatFlags)); // 24-bit in 4 bytes, aligned low
|
||||||
formatFlags |= kAudioFormatFlagIsAlignedHigh;
|
formatFlags |= kAudioFormatFlagIsAlignedHigh;
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(24.4, formatFlags)); // 24-bit in 4 bytes, aligned high
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(24.4, formatFlags)); // 24-bit in 4 bytes, aligned high
|
||||||
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
|
formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(16, formatFlags));
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(16, formatFlags));
|
||||||
physicalFormats.push_back(std::pair<float, uint32_t>(8, formatFlags));
|
physicalFormats.pushBack(etk::Pair<float, uint32_t>(8, formatFlags));
|
||||||
bool setPhysicalFormat = false;
|
bool setPhysicalFormat = false;
|
||||||
for(uint32_t i=0; i<physicalFormats.size(); i++) {
|
for(uint32_t i=0; i<physicalFormats.size(); i++) {
|
||||||
testDescription = description;
|
testDescription = description;
|
||||||
@@ -720,14 +717,14 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
testDescription.mBytesPerFrame = testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;
|
testDescription.mBytesPerFrame = testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;
|
||||||
}
|
}
|
||||||
testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;
|
testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;
|
||||||
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &testDescription);
|
result = AudioObjectSetPropertyData(id, &property, 0, null, 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -741,7 +738,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
dataSize = sizeof(uint32_t);
|
dataSize = sizeof(uint32_t);
|
||||||
property.mSelector = kAudioDevicePropertyLatency;
|
property.mSelector = kAudioDevicePropertyLatency;
|
||||||
if (AudioObjectHasProperty(id, &property) == true) {
|
if (AudioObjectHasProperty(id, &property) == true) {
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &latency);
|
result = AudioObjectGetPropertyData(id, &property, 0, null, &dataSize, &latency);
|
||||||
if (result == kAudioHardwareNoError) {
|
if (result == kAudioHardwareNoError) {
|
||||||
m_latency[ _mode ] = latency;
|
m_latency[ _mode ] = latency;
|
||||||
} else {
|
} else {
|
||||||
@@ -817,10 +814,10 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
bufferBytes *= *_bufferSize;
|
bufferBytes *= *_bufferSize;
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -828,7 +825,7 @@ bool audio::orchestra::api::Core::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
m_sampleRate = _sampleRate;
|
m_sampleRate = _sampleRate;
|
||||||
m_device[modeToIdTable(_mode)] = _device;
|
m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
ATA_VERBOSE("Set state as stopped");
|
ATA_VERBOSE("Set state as stopped");
|
||||||
// Setup the buffer conversion information structure.
|
// Setup the buffer conversion information structure.
|
||||||
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
||||||
@@ -872,19 +869,19 @@ error:
|
|||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
ATA_VERBOSE("Set state as closed");
|
ATA_VERBOSE("Set state as closed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Core::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Core::closeStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("no open stream to close!");
|
ATA_ERROR("no open stream to close!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
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_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
AudioDeviceStop(m_private->id[0], &audio::orchestra::api::Core::callbackEvent);
|
AudioDeviceStop(m_private->id[0], &audio::orchestra::api::Core::callbackEvent);
|
||||||
}
|
}
|
||||||
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
||||||
@@ -897,7 +894,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::closeStream() {
|
|||||||
if ( m_mode == audio::orchestra::mode_input
|
if ( m_mode == audio::orchestra::mode_input
|
||||||
|| ( m_mode == audio::orchestra::mode_duplex
|
|| ( m_mode == audio::orchestra::mode_duplex
|
||||||
&& m_device[0] != m_device[1])) {
|
&& m_device[0] != m_device[1])) {
|
||||||
if (m_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
AudioDeviceStop(m_private->id[1], &audio::orchestra::api::Core::callbackEvent);
|
AudioDeviceStop(m_private->id[1], &audio::orchestra::api::Core::callbackEvent);
|
||||||
}
|
}
|
||||||
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
||||||
@@ -911,10 +908,10 @@ enum audio::orchestra::error audio::orchestra::api::Core::closeStream() {
|
|||||||
m_userBuffer[1].clear();
|
m_userBuffer[1].clear();
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
ATA_VERBOSE("Set state as closed");
|
ATA_VERBOSE("Set state as closed");
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
@@ -925,7 +922,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::startStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -949,7 +946,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::startStream() {
|
|||||||
}
|
}
|
||||||
m_private->drainCounter = 0;
|
m_private->drainCounter = 0;
|
||||||
m_private->internalDrain = false;
|
m_private->internalDrain = false;
|
||||||
m_state = audio::orchestra::state_running;
|
m_state = audio::orchestra::state::running;
|
||||||
ATA_VERBOSE("Set state as running");
|
ATA_VERBOSE("Set state as running");
|
||||||
unlock:
|
unlock:
|
||||||
if (result == noErr) {
|
if (result == noErr) {
|
||||||
@@ -962,7 +959,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::stopStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -970,9 +967,9 @@ enum audio::orchestra::error audio::orchestra::api::Core::stopStream() {
|
|||||||
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_private->drainCounter == 0) {
|
if (m_private->drainCounter == 0) {
|
||||||
std::unique_lock<std::mutex> 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) {
|
||||||
@@ -989,7 +986,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::stopStream() {
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
ATA_VERBOSE("Set state as stopped");
|
ATA_VERBOSE("Set state as stopped");
|
||||||
unlock:
|
unlock:
|
||||||
if (result == noErr) {
|
if (result == noErr) {
|
||||||
@@ -1002,7 +999,7 @@ enum audio::orchestra::error audio::orchestra::api::Core::abortStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -1026,23 +1023,23 @@ bool audio::orchestra::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
const audio::Time& _inTime,
|
const audio::Time& _inTime,
|
||||||
const AudioBufferList *_outBufferList,
|
const AudioBufferList *_outBufferList,
|
||||||
const audio::Time& _outTime) {
|
const audio::Time& _outTime) {
|
||||||
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) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Check if we were draining the stream and signal is finished.
|
// Check if we were draining the stream and signal is finished.
|
||||||
if (m_private->drainCounter > 3) {
|
if (m_private->drainCounter > 3) {
|
||||||
m_state = audio::orchestra::state_stopping;
|
m_state = audio::orchestra::state::stopping;
|
||||||
ATA_VERBOSE("Set state as stopping");
|
ATA_VERBOSE("Set state as stopping");
|
||||||
if (m_private->internalDrain == true) {
|
if (m_private->internalDrain == true) {
|
||||||
new std::thread(&audio::orchestra::api::Core::coreStopStream, this);
|
ETK_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;
|
||||||
}
|
}
|
||||||
@@ -1051,15 +1048,15 @@ bool audio::orchestra::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
// draining stream or duplex mode AND the input/output devices are
|
// draining stream or duplex mode AND the input/output devices are
|
||||||
// different AND this function is called for the input device.
|
// different AND this function is called for the input device.
|
||||||
if (m_private->drainCounter == 0 && (m_mode != audio::orchestra::mode_duplex || _deviceId == outputDevice)) {
|
if (m_private->drainCounter == 0 && (m_mode != audio::orchestra::mode_duplex || _deviceId == outputDevice)) {
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if ( m_mode != audio::orchestra::mode_input
|
if ( m_mode != audio::orchestra::mode_input
|
||||||
&& m_private->xrun[0] == true) {
|
&& m_private->xrun[0] == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
if ( m_mode != audio::orchestra::mode_output
|
if ( m_mode != audio::orchestra::mode_output
|
||||||
&& m_private->xrun[1] == true) {
|
&& m_private->xrun[1] == true) {
|
||||||
status.push_back(audio::orchestra::status_overflow);
|
status.pushBack(audio::orchestra::status::overflow);
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
||||||
@@ -1069,7 +1066,7 @@ bool audio::orchestra::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
if (cbReturnValue == 2) {
|
if (cbReturnValue == 2) {
|
||||||
m_state = audio::orchestra::state_stopping;
|
m_state = audio::orchestra::state::stopping;
|
||||||
ATA_VERBOSE("Set state as stopping");
|
ATA_VERBOSE("Set state as stopping");
|
||||||
m_private->drainCounter = 2;
|
m_private->drainCounter = 2;
|
||||||
abortStream();
|
abortStream();
|
||||||
|
@@ -16,12 +16,12 @@ namespace audio {
|
|||||||
class CorePrivate;
|
class CorePrivate;
|
||||||
class Core: public audio::orchestra::Api {
|
class Core: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Core();
|
Core();
|
||||||
virtual ~Core();
|
virtual ~Core();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_coreOSX;
|
return audio::orchestra::typeCoreOSX;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -46,7 +46,7 @@ namespace audio {
|
|||||||
void* _infoPointer);
|
void* _infoPointer);
|
||||||
static void coreStopStream(void *_userData);
|
static void coreStopStream(void *_userData);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<CorePrivate> m_private;
|
ememory::SharedPtr<CorePrivate> m_private;
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
@@ -13,12 +13,12 @@ namespace audio {
|
|||||||
class CoreIosPrivate;
|
class CoreIosPrivate;
|
||||||
class CoreIos: public audio::orchestra::Api {
|
class CoreIos: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
CoreIos();
|
CoreIos();
|
||||||
virtual ~CoreIos();
|
virtual ~CoreIos();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_coreIOS;
|
return audio::orchestra::typeCoreIOS;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -32,7 +32,7 @@ namespace audio {
|
|||||||
// will most likely produce highly undesireable results!
|
// will most likely produce highly undesireable results!
|
||||||
void callbackEvent();
|
void callbackEvent();
|
||||||
private:
|
private:
|
||||||
std::vector<audio::orchestra::DeviceInfo> m_devices;
|
etk::Vector<audio::orchestra::DeviceInfo> m_devices;
|
||||||
void saveDeviceInfo();
|
void saveDeviceInfo();
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
@@ -47,7 +47,9 @@ namespace audio {
|
|||||||
int32_t _nbChunk,
|
int32_t _nbChunk,
|
||||||
const audio::Time& _time);
|
const audio::Time& _time);
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<CoreIosPrivate> m_private;
|
ememory::SharedPtr<CoreIosPrivate> m_private;
|
||||||
|
uint32_t getDefaultInputDevice();
|
||||||
|
uint32_t getDefaultOutputDevice();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -10,18 +10,17 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <AudioToolbox/AudioToolbox.h>
|
#import <AudioToolbox/AudioToolbox.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
|
||||||
#include <audio/orchestra/debug.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <audio/orchestra/api/CoreIos.h>
|
|
||||||
|
|
||||||
#undef __class__
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#define __class__ "api::CoreIos"
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
extern "C" {
|
||||||
|
#include <limits.h>
|
||||||
|
}
|
||||||
|
#include <audio/orchestra/api/CoreIos.hpp>
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::CoreIos::create() {
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::CoreIos::create() {
|
||||||
ATA_INFO("Create CoreIos device ... ");
|
ATA_INFO("Create CoreIos device ... ");
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::CoreIos());
|
return ememory::SharedPtr<audio::orchestra::api::CoreIos>(ETK_NEW(audio::orchestra::api::CoreIos));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define kOutputBus 0
|
#define kOutputBus 0
|
||||||
@@ -40,53 +39,75 @@ namespace audio {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
audio::orchestra::api::CoreIos::CoreIos(void) :
|
audio::orchestra::api::CoreIos::CoreIos() :
|
||||||
m_private(new audio::orchestra::api::CoreIosPrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::CoreIosPrivate)) {
|
||||||
ATA_INFO("new CoreIos");
|
ATA_INFO("new CoreIos");
|
||||||
int32_t deviceCount = 2;
|
int32_t deviceCount = 2;
|
||||||
ATA_ERROR("Get count devices : " << 2);
|
ATA_ERROR("Get count devices : " << 2);
|
||||||
audio::orchestra::DeviceInfo tmp;
|
audio::orchestra::DeviceInfo tmp;
|
||||||
// Add default output format :
|
// Add default output format :
|
||||||
tmp.name = "speaker";
|
tmp.name = "speaker";
|
||||||
|
tmp.input = false;
|
||||||
tmp.sampleRates.push_back(48000);
|
tmp.sampleRates.push_back(48000);
|
||||||
tmp.channels.push_back(audio::channel_frontRight);
|
tmp.channels.push_back(audio::channel_frontRight);
|
||||||
tmp.channels.push_back(audio::channel_frontLeft);
|
tmp.channels.push_back(audio::channel_frontLeft);
|
||||||
tmp.isDefault = true;
|
|
||||||
tmp.nativeFormats.push_back(audio::format_int16);
|
tmp.nativeFormats.push_back(audio::format_int16);
|
||||||
|
tmp.isDefault = true;
|
||||||
|
tmp.isCorrect = true;
|
||||||
m_devices.push_back(tmp);
|
m_devices.push_back(tmp);
|
||||||
// add default input format:
|
// add default input format:
|
||||||
tmp.name = "microphone";
|
tmp.name = "microphone";
|
||||||
|
tmp.input = true;
|
||||||
tmp.sampleRates.push_back(48000);
|
tmp.sampleRates.push_back(48000);
|
||||||
tmp.channels.push_back(audio::channel_frontRight);
|
tmp.channels.push_back(audio::channel_frontRight);
|
||||||
tmp.channels.push_back(audio::channel_frontLeft);
|
tmp.channels.push_back(audio::channel_frontLeft);
|
||||||
tmp.isDefault = true;
|
|
||||||
tmp.nativeFormats.push_back(audio::format_int16);
|
tmp.nativeFormats.push_back(audio::format_int16);
|
||||||
|
tmp.isDefault = true;
|
||||||
|
tmp.isCorrect = true;
|
||||||
m_devices.push_back(tmp);
|
m_devices.push_back(tmp);
|
||||||
ATA_INFO("Create CoreIOs interface (end)");
|
ATA_INFO("Create CoreIOs interface (end)");
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::CoreIos::~CoreIos(void) {
|
uint32_t audio::orchestra::api::CoreIos::getDefaultInputDevice() {
|
||||||
|
// Should be implemented in subclasses if possible.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t audio::orchestra::api::CoreIos::getDefaultOutputDevice() {
|
||||||
|
// Should be implemented in subclasses if possible.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::orchestra::api::CoreIos::~CoreIos() {
|
||||||
ATA_INFO("Destroy CoreIOs interface");
|
ATA_INFO("Destroy CoreIOs interface");
|
||||||
AudioUnitUninitialize(m_private->audioUnit);
|
AudioUnitUninitialize(m_private->audioUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t audio::orchestra::api::CoreIos::getDeviceCount(void) {
|
uint32_t audio::orchestra::api::CoreIos::getDeviceCount() {
|
||||||
//ATA_INFO("Get device count:"<< m_devices.size());
|
//ATA_INFO("Get device count:"<< m_devices.size());
|
||||||
return m_devices.size();
|
return m_devices.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::DeviceInfo audio::orchestra::api::CoreIos::getDeviceInfo(uint32_t _device) {
|
audio::orchestra::DeviceInfo audio::orchestra::api::CoreIos::getDeviceInfo(uint32_t _device) {
|
||||||
//ATA_INFO("Get device info ...");
|
//ATA_INFO("Get device info ...");
|
||||||
|
if (_device >= m_devices.size()) {
|
||||||
|
audio::orchestra::DeviceInfo tmp;
|
||||||
|
tmp.sampleRates.push_back(0);
|
||||||
|
tmp.channels.push_back(audio::channel_frontCenter);
|
||||||
|
tmp.isDefault = false;
|
||||||
|
tmp.nativeFormats.push_back(audio::format_int8);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
return m_devices[_device];
|
return m_devices[_device];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::CoreIos::closeStream(void) {
|
enum audio::orchestra::error audio::orchestra::api::CoreIos::closeStream() {
|
||||||
ATA_INFO("Close Stream");
|
ATA_INFO("Close Stream");
|
||||||
// Can not close the stream now...
|
// Can not close the stream now...
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::CoreIos::startStream(void) {
|
enum audio::orchestra::error audio::orchestra::api::CoreIos::startStream() {
|
||||||
ATA_INFO("Start Stream");
|
ATA_INFO("Start Stream");
|
||||||
// TODO : Check return ...
|
// TODO : Check return ...
|
||||||
audio::orchestra::Api::startStream();
|
audio::orchestra::Api::startStream();
|
||||||
@@ -95,14 +116,14 @@ enum audio::orchestra::error audio::orchestra::api::CoreIos::startStream(void) {
|
|||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::CoreIos::stopStream(void) {
|
enum audio::orchestra::error audio::orchestra::api::CoreIos::stopStream() {
|
||||||
ATA_INFO("Stop stream");
|
ATA_INFO("Stop stream");
|
||||||
OSStatus status = AudioOutputUnitStop(m_private->audioUnit);
|
OSStatus status = AudioOutputUnitStop(m_private->audioUnit);
|
||||||
// Can not close the stream now...
|
// Can not close the stream now...
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::CoreIos::abortStream(void) {
|
enum audio::orchestra::error audio::orchestra::api::CoreIos::abortStream() {
|
||||||
ATA_INFO("Abort Stream");
|
ATA_INFO("Abort Stream");
|
||||||
OSStatus status = AudioOutputUnitStop(m_private->audioUnit);
|
OSStatus status = AudioOutputUnitStop(m_private->audioUnit);
|
||||||
// Can not close the stream now...
|
// Can not close the stream now...
|
||||||
@@ -113,19 +134,34 @@ 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_doConvertBuffer[modeToIdTable(audio::orchestra::mode_output)] == true) {
|
if ( m_mode == audio::orchestra::mode_output
|
||||||
doStopStream = m_callback(nullptr,
|
|| m_mode == audio::orchestra::mode_duplex) {
|
||||||
audio::Time(),
|
if (m_doConvertBuffer[modeToIdTable(audio::orchestra::mode_output)] == true) {
|
||||||
&m_userBuffer[modeToIdTable(audio::orchestra::mode_output)][0],
|
ATA_INFO("get output DATA : " << uint64_t(&m_userBuffer[modeToIdTable(audio::orchestra::mode_output)][0]));
|
||||||
_time,
|
doStopStream = m_callback(null,
|
||||||
_nbChunk,
|
audio::Time(),
|
||||||
status);
|
&m_userBuffer[modeToIdTable(audio::orchestra::mode_output)][0],
|
||||||
convertBuffer((char*)_data, &m_userBuffer[modeToIdTable(audio::orchestra::mode_output)][0], m_convertInfo[modeToIdTable(audio::orchestra::mode_output)]);
|
_time,
|
||||||
} else {
|
_nbChunk,
|
||||||
|
status);
|
||||||
|
convertBuffer((char*)_data, &m_userBuffer[modeToIdTable(audio::orchestra::mode_output)][0], m_convertInfo[modeToIdTable(audio::orchestra::mode_output)]);
|
||||||
|
} else {
|
||||||
|
ATA_INFO("have output DATA : " << uint64_t(_data));
|
||||||
|
doStopStream = m_callback(null,
|
||||||
|
_time,
|
||||||
|
_data,
|
||||||
|
audio::Time(),
|
||||||
|
_nbChunk,
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( m_mode == audio::orchestra::mode_input
|
||||||
|
|| m_mode == audio::orchestra::mode_duplex) {
|
||||||
|
ATA_INFO("have input DATA : " << uint64_t(_data));
|
||||||
doStopStream = m_callback(_data,
|
doStopStream = m_callback(_data,
|
||||||
_time,
|
_time,
|
||||||
nullptr,
|
null,
|
||||||
audio::Time(),
|
audio::Time(),
|
||||||
_nbChunk,
|
_nbChunk,
|
||||||
status);
|
status);
|
||||||
@@ -144,12 +180,12 @@ static OSStatus playbackCallback(void *_userData,
|
|||||||
uint32_t _inBusNumber,
|
uint32_t _inBusNumber,
|
||||||
uint32_t _inNumberFrames,
|
uint32_t _inNumberFrames,
|
||||||
AudioBufferList* _ioData) {
|
AudioBufferList* _ioData) {
|
||||||
if (_userData == nullptr) {
|
if (_userData == null) {
|
||||||
ATA_ERROR("callback event ... nullptr pointer");
|
ATA_ERROR("callback event ... null pointer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
audio::Time tmpTimeime;
|
audio::Time tmpTimeime;
|
||||||
if (_inTime != nullptr) {
|
if (_inTime != null) {
|
||||||
tmpTimeime = audio::Time(_inTime->mHostTime/1000000000LL, _inTime->mHostTime%1000000000LL);
|
tmpTimeime = audio::Time(_inTime->mHostTime/1000000000LL, _inTime->mHostTime%1000000000LL);
|
||||||
}
|
}
|
||||||
audio::orchestra::api::CoreIos* myClass = static_cast<audio::orchestra::api::CoreIos*>(_userData);
|
audio::orchestra::api::CoreIos* myClass = static_cast<audio::orchestra::api::CoreIos*>(_userData);
|
||||||
@@ -157,7 +193,7 @@ static OSStatus playbackCallback(void *_userData,
|
|||||||
for (int32_t iii=0; iii < _ioData->mNumberBuffers; iii++) {
|
for (int32_t iii=0; iii < _ioData->mNumberBuffers; iii++) {
|
||||||
AudioBuffer buffer = _ioData->mBuffers[iii];
|
AudioBuffer buffer = _ioData->mBuffers[iii];
|
||||||
int32_t numberFrame = buffer.mDataByteSize/2/*stereo*/ /sizeof(int16_t);
|
int32_t numberFrame = buffer.mDataByteSize/2/*stereo*/ /sizeof(int16_t);
|
||||||
ATA_VERBOSE("request data size: " << numberFrame << " busNumber=" << _inBusNumber);
|
ATA_INFO("request data size: " << numberFrame << " busNumber=" << _inBusNumber);
|
||||||
myClass->callBackEvent(buffer.mData, numberFrame, tmpTimeime);
|
myClass->callBackEvent(buffer.mData, numberFrame, tmpTimeime);
|
||||||
}
|
}
|
||||||
return noErr;
|
return noErr;
|
||||||
@@ -178,7 +214,8 @@ bool audio::orchestra::api::CoreIos::open(uint32_t _device,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
// TODO : This is a bad ack ....
|
||||||
|
m_mode = audio::orchestra::mode_output;
|
||||||
// configure Airtaudio internal configuration:
|
// configure Airtaudio internal configuration:
|
||||||
m_userFormat = _format;
|
m_userFormat = _format;
|
||||||
m_nUserChannels[modeToIdTable(_mode)] = _channels;
|
m_nUserChannels[modeToIdTable(_mode)] = _channels;
|
||||||
@@ -230,7 +267,7 @@ bool audio::orchestra::api::CoreIos::open(uint32_t _device,
|
|||||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||||
|
|
||||||
// Get component
|
// Get component
|
||||||
AudioComponent inputComponent = AudioComponentFindNext(nullptr, &desc);
|
AudioComponent inputComponent = AudioComponentFindNext(null, &desc);
|
||||||
|
|
||||||
// Get audio units
|
// Get audio units
|
||||||
status = AudioComponentInstanceNew(inputComponent, &m_private->audioUnit);
|
status = AudioComponentInstanceNew(inputComponent, &m_private->audioUnit);
|
||||||
@@ -241,11 +278,11 @@ bool audio::orchestra::api::CoreIos::open(uint32_t _device,
|
|||||||
uint32_t flag = 1;
|
uint32_t flag = 1;
|
||||||
// Enable IO for playback
|
// Enable IO for playback
|
||||||
status = AudioUnitSetProperty(m_private->audioUnit,
|
status = AudioUnitSetProperty(m_private->audioUnit,
|
||||||
kAudioOutputUnitProperty_EnableIO,
|
kAudioOutputUnitProperty_EnableIO,
|
||||||
kAudioUnitScope_Output,
|
kAudioUnitScope_Output,
|
||||||
kOutputBus,
|
kOutputBus,
|
||||||
&flag,
|
&flag,
|
||||||
sizeof(flag));
|
sizeof(flag));
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ATA_ERROR("can not request audio autorisation...");
|
ATA_ERROR("can not request audio autorisation...");
|
||||||
}
|
}
|
||||||
@@ -263,11 +300,11 @@ bool audio::orchestra::api::CoreIos::open(uint32_t _device,
|
|||||||
audioFormat.mReserved = 0;
|
audioFormat.mReserved = 0;
|
||||||
// Apply format
|
// Apply format
|
||||||
status = AudioUnitSetProperty(m_private->audioUnit,
|
status = AudioUnitSetProperty(m_private->audioUnit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Input,
|
kAudioUnitScope_Input,
|
||||||
kOutputBus,
|
kOutputBus,
|
||||||
&audioFormat,
|
&audioFormat,
|
||||||
sizeof(audioFormat));
|
sizeof(audioFormat));
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ATA_ERROR("can not set stream properties...");
|
ATA_ERROR("can not set stream properties...");
|
||||||
}
|
}
|
||||||
@@ -278,11 +315,11 @@ bool audio::orchestra::api::CoreIos::open(uint32_t _device,
|
|||||||
callbackStruct.inputProc = &playbackCallback;
|
callbackStruct.inputProc = &playbackCallback;
|
||||||
callbackStruct.inputProcRefCon = this;
|
callbackStruct.inputProcRefCon = this;
|
||||||
status = AudioUnitSetProperty(m_private->audioUnit,
|
status = AudioUnitSetProperty(m_private->audioUnit,
|
||||||
kAudioUnitProperty_SetRenderCallback,
|
kAudioUnitProperty_SetRenderCallback,
|
||||||
kAudioUnitScope_Global,
|
kAudioUnitScope_Global,
|
||||||
kOutputBus,
|
kOutputBus,
|
||||||
&callbackStruct,
|
&callbackStruct,
|
||||||
sizeof(callbackStruct));
|
sizeof(callbackStruct));
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ATA_ERROR("can not set Callback...");
|
ATA_ERROR("can not set Callback...");
|
||||||
}
|
}
|
||||||
|
@@ -7,16 +7,13 @@
|
|||||||
|
|
||||||
// Windows DirectSound API
|
// Windows DirectSound API
|
||||||
#if defined(ORCHESTRA_BUILD_DS)
|
#if defined(ORCHESTRA_BUILD_DS)
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <ethread/tools.h>
|
#include <ethread/tools.hpp>
|
||||||
#include <audio/orchestra/api/Ds.h>
|
#include <audio/orchestra/api/Ds.hpp>
|
||||||
|
|
||||||
#undef __class__
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Ds::create() {
|
||||||
#define __class__ "api::Ds"
|
return ememory::SharedPtr<audio::orchestra::api::Ds>(ETK_NEW(audio::orchestra::api::Ds));
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Ds::create() {
|
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Ds());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -26,11 +23,10 @@ std::shared_ptr<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 <assert.h>
|
#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 */
|
||||||
@@ -62,7 +58,7 @@ class DsDevice {
|
|||||||
public:
|
public:
|
||||||
LPGUID id;
|
LPGUID id;
|
||||||
bool input;
|
bool input;
|
||||||
std::string name;
|
etk::String name;
|
||||||
DsDevice() :
|
DsDevice() :
|
||||||
id(0),
|
id(0),
|
||||||
input(false) {
|
input(false) {
|
||||||
@@ -75,7 +71,7 @@ namespace audio {
|
|||||||
namespace api {
|
namespace api {
|
||||||
class DsPrivate {
|
class DsPrivate {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<std::thread> thread;
|
ememory::SharedPtr<ethread::Thread> thread;
|
||||||
bool threadRunning;
|
bool threadRunning;
|
||||||
uint32_t drainCounter; // Tracks callback counts when draining
|
uint32_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.
|
||||||
@@ -86,7 +82,7 @@ namespace audio {
|
|||||||
DWORD dsBufferSize[2];
|
DWORD dsBufferSize[2];
|
||||||
DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
|
DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
|
||||||
HANDLE condition;
|
HANDLE condition;
|
||||||
std::vector<DsDevice> dsDevices;
|
etk::Vector<DsDevice> dsDevices;
|
||||||
DsPrivate() :
|
DsPrivate() :
|
||||||
threadRunning(false),
|
threadRunning(false),
|
||||||
drainCounter(0),
|
drainCounter(0),
|
||||||
@@ -110,15 +106,15 @@ static const char* getErrorString(int32_t _code);
|
|||||||
|
|
||||||
struct DsProbeData {
|
struct DsProbeData {
|
||||||
bool isInput;
|
bool isInput;
|
||||||
std::vector<DsDevice>* dsDevices;
|
etk::Vector<DsDevice>* dsDevices;
|
||||||
};
|
};
|
||||||
|
|
||||||
audio::orchestra::api::Ds::Ds() :
|
audio::orchestra::api::Ds::Ds() :
|
||||||
m_private(new audio::orchestra::api::DsPrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::DsPrivate)) {
|
||||||
// Dsound will run both-threaded. If CoInitialize fails, then just
|
// Dsound will run both-threaded. If CoInitialize fails, then just
|
||||||
// accept whatever the mainline chose for a threading model.
|
// accept whatever the mainline chose for a threading model.
|
||||||
m_coInitialized = false;
|
m_coInitialized = false;
|
||||||
HRESULT hr = CoInitialize(nullptr);
|
HRESULT hr = CoInitialize(null);
|
||||||
if (!FAILED(hr)) {
|
if (!FAILED(hr)) {
|
||||||
m_coInitialized = true;
|
m_coInitialized = true;
|
||||||
}
|
}
|
||||||
@@ -128,20 +124,20 @@ audio::orchestra::api::Ds::~Ds() {
|
|||||||
if (m_coInitialized) {
|
if (m_coInitialized) {
|
||||||
CoUninitialize(); // balanced call.
|
CoUninitialize(); // balanced call.
|
||||||
}
|
}
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "tchar.h"
|
#include "tchar.h"
|
||||||
static std::string convertTChar(LPCTSTR _name) {
|
static etk::String convertTChar(LPCTSTR _name) {
|
||||||
#if defined(UNICODE) || defined(_UNICODE)
|
#if defined(UNICODE) || defined(_UNICODE)
|
||||||
int32_t length = WideCharToMultiByte(CP_UTF8, 0, _name, -1, nullptr, 0, nullptr, nullptr);
|
int32_t length = WideCharToMultiByte(CP_UTF8, 0, _name, -1, null, 0, null, null);
|
||||||
std::string s(length-1, '\0');
|
etk::String s(length-1, '\0');
|
||||||
WideCharToMultiByte(CP_UTF8, 0, _name, -1, &s[0], length, nullptr, nullptr);
|
WideCharToMultiByte(CP_UTF8, 0, _name, -1, &s[0], length, null, null);
|
||||||
#else
|
#else
|
||||||
std::string s(_name);
|
etk::String s(_name);
|
||||||
#endif
|
#endif
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -151,13 +147,13 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
LPCTSTR _module,
|
LPCTSTR _module,
|
||||||
LPVOID _lpContext) {
|
LPVOID _lpContext) {
|
||||||
struct DsProbeData& probeInfo = *(struct DsProbeData*) _lpContext;
|
struct DsProbeData& probeInfo = *(struct DsProbeData*) _lpContext;
|
||||||
std::vector<DsDevice>& dsDevices = *probeInfo.dsDevices;
|
etk::Vector<DsDevice>& dsDevices = *probeInfo.dsDevices;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
bool validDevice = false;
|
bool validDevice = false;
|
||||||
if (probeInfo.isInput == true) {
|
if (probeInfo.isInput == true) {
|
||||||
DSCCAPS caps;
|
DSCCAPS caps;
|
||||||
LPDIRECTSOUNDCAPTURE object;
|
LPDIRECTSOUNDCAPTURE object;
|
||||||
hr = DirectSoundCaptureCreate(_lpguid, &object, nullptr);
|
hr = DirectSoundCaptureCreate(_lpguid, &object, null);
|
||||||
if (hr != DS_OK) {
|
if (hr != DS_OK) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -172,7 +168,7 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
} else {
|
} else {
|
||||||
DSCAPS caps;
|
DSCAPS caps;
|
||||||
LPDIRECTSOUND object;
|
LPDIRECTSOUND object;
|
||||||
hr = DirectSoundCreate(_lpguid, &object, nullptr);
|
hr = DirectSoundCreate(_lpguid, &object, null);
|
||||||
if (hr != DS_OK) {
|
if (hr != DS_OK) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -190,16 +186,16 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
// If good device, then save its name and guid.
|
// If good device, then save its name and guid.
|
||||||
std::string name = convertTChar(_description);
|
etk::String name = convertTChar(_description);
|
||||||
//if (name == "Primary Sound Driver" || name == "Primary Sound Capture Driver")
|
//if (name == "Primary Sound Driver" || name == "Primary Sound Capture Driver")
|
||||||
if (_lpguid == nullptr) {
|
if (_lpguid == null) {
|
||||||
name = "Default Device";
|
name = "Default Device";
|
||||||
}
|
}
|
||||||
DsDevice device;
|
DsDevice device;
|
||||||
device.name = name;
|
device.name = name;
|
||||||
device.input = probeInfo.isInput;
|
device.input = probeInfo.isInput;
|
||||||
device.id = _lpguid;
|
device.id = _lpguid;
|
||||||
dsDevices.push_back(device);
|
dsDevices.pushBack(device);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +233,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
|
|||||||
info.input = true;
|
info.input = true;
|
||||||
LPDIRECTSOUND output;
|
LPDIRECTSOUND output;
|
||||||
DSCAPS outCaps;
|
DSCAPS outCaps;
|
||||||
result = DirectSoundCreate(m_private->dsDevices[_device].id, &output, nullptr);
|
result = DirectSoundCreate(m_private->dsDevices[_device].id, &output, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": opening output device (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": opening output device (" << m_private->dsDevices[_device].name << ")!");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -253,24 +249,24 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
|
|||||||
}
|
}
|
||||||
// Get output channel information.
|
// Get output channel information.
|
||||||
if (outCaps.dwFlags & DSCAPS_PRIMARYSTEREO) {
|
if (outCaps.dwFlags & DSCAPS_PRIMARYSTEREO) {
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
} else {
|
} else {
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
}
|
}
|
||||||
// Get sample rate information.
|
// Get sample rate information.
|
||||||
for (auto &it : audio::orchestra::genericSampleRate()) {
|
for (auto &it : audio::orchestra::genericSampleRate()) {
|
||||||
if ( it >= outCaps.dwMinSecondarySampleRate
|
if ( it >= outCaps.dwMinSecondarySampleRate
|
||||||
&& it <= outCaps.dwMaxSecondarySampleRate) {
|
&& it <= outCaps.dwMaxSecondarySampleRate) {
|
||||||
info.sampleRates.push_back(it);
|
info.sampleRates.pushBack(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get format information.
|
// Get format information.
|
||||||
if (outCaps.dwFlags & DSCAPS_PRIMARY16BIT) {
|
if (outCaps.dwFlags & DSCAPS_PRIMARY16BIT) {
|
||||||
info.nativeFormats.push_back(audio::format_int16);
|
info.nativeFormats.pushBack(audio::format_int16);
|
||||||
}
|
}
|
||||||
if (outCaps.dwFlags & DSCAPS_PRIMARY8BIT) {
|
if (outCaps.dwFlags & DSCAPS_PRIMARY8BIT) {
|
||||||
info.nativeFormats.push_back(audio::format_int8);
|
info.nativeFormats.pushBack(audio::format_int8);
|
||||||
}
|
}
|
||||||
output->Release();
|
output->Release();
|
||||||
info.name = m_private->dsDevices[_device].name;
|
info.name = m_private->dsDevices[_device].name;
|
||||||
@@ -278,7 +274,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
|
|||||||
return info;
|
return info;
|
||||||
} else {
|
} else {
|
||||||
LPDIRECTSOUNDCAPTURE input;
|
LPDIRECTSOUNDCAPTURE input;
|
||||||
result = DirectSoundCaptureCreate(m_private->dsDevices[_device].id, &input, nullptr);
|
result = DirectSoundCaptureCreate(m_private->dsDevices[_device].id, &input, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": opening input device (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": opening input device (" << m_private->dsDevices[_device].name << ")!");
|
||||||
info.clear();
|
info.clear();
|
||||||
@@ -295,67 +291,67 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
|
|||||||
}
|
}
|
||||||
// Get input channel information.
|
// Get input channel information.
|
||||||
for (int32_t iii=0; iii<inCaps.dwChannels; ++iii) {
|
for (int32_t iii=0; iii<inCaps.dwChannels; ++iii) {
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
}
|
}
|
||||||
// Get sample rate and format information.
|
// Get sample rate and format information.
|
||||||
std::vector<uint32_t> rates;
|
etk::Vector<uint32_t> rates;
|
||||||
if (inCaps.dwChannels >= 2) {
|
if (inCaps.dwChannels >= 2) {
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96S16) ) {
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S16) ) {
|
||||||
info.nativeFormats.push_back(audio::format_int16);
|
info.nativeFormats.pushBack(audio::format_int16);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1S08)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2S08)
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4S08)
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ) {
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ) {
|
||||||
info.nativeFormats.push_back(audio::format_int8);
|
info.nativeFormats.pushBack(audio::format_int8);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_1S08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_1S08) ){
|
||||||
rates.push_back(11025);
|
rates.pushBack(11025);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2S08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S08) ){
|
||||||
rates.push_back(22050);
|
rates.pushBack(22050);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4S08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S08) ){
|
||||||
rates.push_back(44100);
|
rates.pushBack(44100);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_96S16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_96S16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ){
|
||||||
rates.push_back(96000);
|
rates.pushBack(96000);
|
||||||
}
|
}
|
||||||
} else if (inCaps.dwChannels == 1) {
|
} else if (inCaps.dwChannels == 1) {
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96M16) ) {
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M16) ) {
|
||||||
info.nativeFormats.push_back(audio::format_int16);
|
info.nativeFormats.pushBack(audio::format_int16);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1M08)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2M08)
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4M08)
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M08)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ) {
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ) {
|
||||||
info.nativeFormats.push_back(audio::format_int8);
|
info.nativeFormats.pushBack(audio::format_int8);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_1M08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_1M08) ){
|
||||||
rates.push_back(11025);
|
rates.pushBack(11025);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_2M08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M08) ){
|
||||||
rates.push_back(22050);
|
rates.pushBack(22050);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_4M08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M08) ){
|
||||||
rates.push_back(44100);
|
rates.pushBack(44100);
|
||||||
}
|
}
|
||||||
if ( (inCaps.dwFormats & WAVE_FORMAT_96M16)
|
if ( (inCaps.dwFormats & WAVE_FORMAT_96M16)
|
||||||
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ){
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ){
|
||||||
rates.push_back(96000);
|
rates.pushBack(96000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// technically, this would be an error
|
// technically, this would be an error
|
||||||
@@ -377,10 +373,10 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Ds::getDeviceInfo(uint32_t _
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found == false) {
|
if (found == false) {
|
||||||
info.sampleRates.push_back(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;
|
||||||
@@ -456,7 +452,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
HRESULT result;
|
HRESULT result;
|
||||||
if (_mode == audio::orchestra::mode_output) {
|
if (_mode == audio::orchestra::mode_output) {
|
||||||
LPDIRECTSOUND output;
|
LPDIRECTSOUND output;
|
||||||
result = DirectSoundCreate(m_private->dsDevices[_device].id, &output, nullptr);
|
result = DirectSoundCreate(m_private->dsDevices[_device].id, &output, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": opening output device (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": opening output device (" << m_private->dsDevices[_device].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
@@ -513,7 +509,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||||
// Obtain the primary buffer
|
// Obtain the primary buffer
|
||||||
LPDIRECTSOUNDBUFFER buffer;
|
LPDIRECTSOUNDBUFFER buffer;
|
||||||
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
result = output->CreateSoundBuffer(&bufferDescription, &buffer, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR(getErrorString(result) << ": accessing primary buffer (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": accessing primary buffer (" << m_private->dsDevices[_device].name << ")!");
|
||||||
@@ -537,13 +533,13 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
bufferDescription.lpwfxFormat = &waveFormat;
|
bufferDescription.lpwfxFormat = &waveFormat;
|
||||||
// Try to create the secondary DS buffer. If that doesn't work,
|
// Try to create the secondary DS buffer. If that doesn't work,
|
||||||
// try to use software mixing. Otherwise, there's a problem.
|
// try to use software mixing. Otherwise, there's a problem.
|
||||||
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
result = output->CreateSoundBuffer(&bufferDescription, &buffer, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS
|
bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS
|
||||||
| DSBCAPS_GLOBALFOCUS
|
| DSBCAPS_GLOBALFOCUS
|
||||||
| DSBCAPS_GETCURRENTPOSITION2
|
| DSBCAPS_GETCURRENTPOSITION2
|
||||||
| DSBCAPS_LOCSOFTWARE); // Force software mixing
|
| DSBCAPS_LOCSOFTWARE); // Force software mixing
|
||||||
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
result = output->CreateSoundBuffer(&bufferDescription, &buffer, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR(getErrorString(result) << ": creating secondary buffer (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": creating secondary buffer (" << m_private->dsDevices[_device].name << ")!");
|
||||||
@@ -564,7 +560,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
// Lock the DS buffer
|
// Lock the DS buffer
|
||||||
LPVOID audioPtr;
|
LPVOID audioPtr;
|
||||||
DWORD dataLen;
|
DWORD dataLen;
|
||||||
result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, nullptr, nullptr, 0);
|
result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, null, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
@@ -574,7 +570,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
// Zero the DS buffer
|
// Zero the DS buffer
|
||||||
ZeroMemory(audioPtr, dataLen);
|
ZeroMemory(audioPtr, dataLen);
|
||||||
// Unlock the DS buffer
|
// Unlock the DS buffer
|
||||||
result = buffer->Unlock(audioPtr, dataLen, nullptr, 0);
|
result = buffer->Unlock(audioPtr, dataLen, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
@@ -586,7 +582,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
if (_mode == audio::orchestra::mode_input) {
|
if (_mode == audio::orchestra::mode_input) {
|
||||||
LPDIRECTSOUNDCAPTURE input;
|
LPDIRECTSOUNDCAPTURE input;
|
||||||
result = DirectSoundCaptureCreate(m_private->dsDevices[_device].id, &input, nullptr);
|
result = DirectSoundCaptureCreate(m_private->dsDevices[_device].id, &input, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": opening input device (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": opening input device (" << m_private->dsDevices[_device].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
@@ -646,7 +642,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
bufferDescription.lpwfxFormat = &waveFormat;
|
bufferDescription.lpwfxFormat = &waveFormat;
|
||||||
// Create the capture buffer.
|
// Create the capture buffer.
|
||||||
LPDIRECTSOUNDCAPTUREBUFFER buffer;
|
LPDIRECTSOUNDCAPTUREBUFFER buffer;
|
||||||
result = input->CreateCaptureBuffer(&bufferDescription, &buffer, nullptr);
|
result = input->CreateCaptureBuffer(&bufferDescription, &buffer, null);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
ATA_ERROR(getErrorString(result) << ": creating input buffer (" << m_private->dsDevices[_device].name << ")!");
|
ATA_ERROR(getErrorString(result) << ": creating input buffer (" << m_private->dsDevices[_device].name << ")!");
|
||||||
@@ -670,7 +666,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
// Lock the capture buffer
|
// Lock the capture buffer
|
||||||
LPVOID audioPtr;
|
LPVOID audioPtr;
|
||||||
DWORD dataLen;
|
DWORD dataLen;
|
||||||
result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, nullptr, nullptr, 0);
|
result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, null, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
@@ -680,7 +676,7 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
// Zero the buffer
|
// Zero the buffer
|
||||||
ZeroMemory(audioPtr, dataLen);
|
ZeroMemory(audioPtr, dataLen);
|
||||||
// Unlock the buffer
|
// Unlock the buffer
|
||||||
result = buffer->Unlock(audioPtr, dataLen, nullptr, 0);
|
result = buffer->Unlock(audioPtr, dataLen, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
@@ -732,23 +728,23 @@ bool audio::orchestra::api::Ds::open(uint32_t _device,
|
|||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
}
|
}
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create a manual-reset event.
|
// Create a manual-reset event.
|
||||||
m_private->condition = CreateEvent(nullptr, // no security
|
m_private->condition = CreateEvent(null, // no security
|
||||||
TRUE, // manual-reset
|
TRUE, // manual-reset
|
||||||
FALSE, // non-signaled initially
|
FALSE, // non-signaled initially
|
||||||
nullptr); // unnamed
|
null); // unnamed
|
||||||
m_private->id[modeToIdTable(_mode)] = ohandle;
|
m_private->id[modeToIdTable(_mode)] = ohandle;
|
||||||
m_private->buffer[modeToIdTable(_mode)] = bhandle;
|
m_private->buffer[modeToIdTable(_mode)] = bhandle;
|
||||||
m_private->dsBufferSize[modeToIdTable(_mode)] = dsBufferSize;
|
m_private->dsBufferSize[modeToIdTable(_mode)] = dsBufferSize;
|
||||||
m_private->dsPointerLeadTime[modeToIdTable(_mode)] = dsPointerLeadTime;
|
m_private->dsPointerLeadTime[modeToIdTable(_mode)] = dsPointerLeadTime;
|
||||||
m_device[modeToIdTable(_mode)] = _device;
|
m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
if ( m_mode == audio::orchestra::mode_output
|
if ( m_mode == audio::orchestra::mode_output
|
||||||
&& _mode == audio::orchestra::mode_input) {
|
&& _mode == audio::orchestra::mode_input) {
|
||||||
// We had already set up an output stream.
|
// We had already set up an output stream.
|
||||||
@@ -765,19 +761,19 @@ 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;
|
||||||
std::shared_ptr<std::thread> tmpThread(new std::thread(&audio::orchestra::api::Ds::dsCallbackEvent, this));
|
ememory::SharedPtr<ethread::Thread> tmpThread(ETK_NEW(ethread::Thread, [=](){audio::orchestra::api::Ds::dsCallbackEvent();});
|
||||||
m_private->thread = std::move(tmpThread);
|
m_private->thread = etk::move(tmpThread);
|
||||||
if (m_private->thread == nullptr) {
|
if (m_private->thread == null) {
|
||||||
ATA_ERROR("error creating callback thread!");
|
ATA_ERROR("error creating callback thread!");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
// Boost DS thread priority
|
// Boost DS thread priority
|
||||||
etk::thread::setPriority(*m_private->thread, -6);
|
ethread::setPriority(*m_private->thread, -6);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
error:
|
error:
|
||||||
if (m_private->buffer[0]) {
|
if (m_private->buffer[0]) {
|
||||||
// the object pointer can be nullptr and valid
|
// the object pointer can be null and valid
|
||||||
LPDIRECTSOUND object = (LPDIRECTSOUND) m_private->id[0];
|
LPDIRECTSOUND object = (LPDIRECTSOUND) m_private->id[0];
|
||||||
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
@@ -788,7 +784,7 @@ error:
|
|||||||
if (m_private->buffer[1]) {
|
if (m_private->buffer[1]) {
|
||||||
LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) m_private->id[1];
|
LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) m_private->id[1];
|
||||||
LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
||||||
if (buffer != nullptr) {
|
if (buffer != null) {
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,22 +796,22 @@ error:
|
|||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Ds::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Ds::closeStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("no open stream to close!");
|
ATA_ERROR("no open stream to close!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
// Stop the callback thread.
|
// Stop the callback thread.
|
||||||
m_private->threadRunning = false;
|
m_private->threadRunning = false;
|
||||||
if (m_private->thread != nullptr) {
|
if (m_private->thread != null) {
|
||||||
m_private->thread->join();
|
m_private->thread->join();
|
||||||
m_private->thread = nullptr;
|
m_private->thread = null;
|
||||||
}
|
}
|
||||||
if (m_private->buffer[0]) { // the object pointer can be nullptr and valid
|
if (m_private->buffer[0]) { // the object pointer can be null and valid
|
||||||
LPDIRECTSOUND object = (LPDIRECTSOUND) m_private->id[0];
|
LPDIRECTSOUND object = (LPDIRECTSOUND) m_private->id[0];
|
||||||
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
@@ -842,7 +838,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::closeStream() {
|
|||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Ds::startStream() {
|
enum audio::orchestra::error audio::orchestra::api::Ds::startStream() {
|
||||||
@@ -851,7 +847,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::startStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -887,7 +883,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::startStream() {
|
|||||||
m_private->drainCounter = 0;
|
m_private->drainCounter = 0;
|
||||||
m_private->internalDrain = false;
|
m_private->internalDrain = false;
|
||||||
ResetEvent(m_private->condition);
|
ResetEvent(m_private->condition);
|
||||||
m_state = audio::orchestra::state_running;
|
m_state = audio::orchestra::state::running;
|
||||||
unlock:
|
unlock:
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
return audio::orchestra::error_systemError;
|
return audio::orchestra::error_systemError;
|
||||||
@@ -899,7 +895,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -912,7 +908,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
m_private->drainCounter = 2;
|
m_private->drainCounter = 2;
|
||||||
WaitForSingleObject(m_private->condition, INFINITE); // block until signaled
|
WaitForSingleObject(m_private->condition, INFINITE); // block until signaled
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
// Stop the buffer and clear memory
|
// Stop the buffer and clear memory
|
||||||
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
||||||
result = buffer->Stop();
|
result = buffer->Stop();
|
||||||
@@ -922,7 +918,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
}
|
}
|
||||||
// Lock the buffer and clear it so that if we start to play again,
|
// Lock the buffer and clear it so that if we start to play again,
|
||||||
// we won't have old data playing.
|
// we won't have old data playing.
|
||||||
result = buffer->Lock(0, m_private->dsBufferSize[0], &audioPtr, &dataLen, nullptr, nullptr, 0);
|
result = buffer->Lock(0, m_private->dsBufferSize[0], &audioPtr, &dataLen, null, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": locking output buffer!");
|
ATA_ERROR(getErrorString(result) << ": locking output buffer!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -930,7 +926,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
// Zero the DS buffer
|
// Zero the DS buffer
|
||||||
ZeroMemory(audioPtr, dataLen);
|
ZeroMemory(audioPtr, dataLen);
|
||||||
// Unlock the DS buffer
|
// Unlock the DS buffer
|
||||||
result = buffer->Unlock(audioPtr, dataLen, nullptr, 0);
|
result = buffer->Unlock(audioPtr, dataLen, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": unlocking output buffer!");
|
ATA_ERROR(getErrorString(result) << ": unlocking output buffer!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -941,9 +937,9 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
if ( m_mode == audio::orchestra::mode_input
|
if ( m_mode == audio::orchestra::mode_input
|
||||||
|| m_mode == audio::orchestra::mode_duplex) {
|
|| m_mode == audio::orchestra::mode_duplex) {
|
||||||
LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
||||||
audioPtr = nullptr;
|
audioPtr = null;
|
||||||
dataLen = 0;
|
dataLen = 0;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
result = buffer->Stop();
|
result = buffer->Stop();
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": stopping input buffer!");
|
ATA_ERROR(getErrorString(result) << ": stopping input buffer!");
|
||||||
@@ -951,7 +947,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
}
|
}
|
||||||
// Lock the buffer and clear it so that if we start to play again,
|
// Lock the buffer and clear it so that if we start to play again,
|
||||||
// we won't have old data playing.
|
// we won't have old data playing.
|
||||||
result = buffer->Lock(0, m_private->dsBufferSize[1], &audioPtr, &dataLen, nullptr, nullptr, 0);
|
result = buffer->Lock(0, m_private->dsBufferSize[1], &audioPtr, &dataLen, null, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": locking input buffer!");
|
ATA_ERROR(getErrorString(result) << ": locking input buffer!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -959,7 +955,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::stopStream() {
|
|||||||
// Zero the DS buffer
|
// Zero the DS buffer
|
||||||
ZeroMemory(audioPtr, dataLen);
|
ZeroMemory(audioPtr, dataLen);
|
||||||
// Unlock the DS buffer
|
// Unlock the DS buffer
|
||||||
result = buffer->Unlock(audioPtr, dataLen, nullptr, 0);
|
result = buffer->Unlock(audioPtr, dataLen, null, 0);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": unlocking input buffer!");
|
ATA_ERROR(getErrorString(result) << ": unlocking input buffer!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -979,7 +975,7 @@ enum audio::orchestra::error audio::orchestra::api::Ds::abortStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -989,17 +985,18 @@ enum audio::orchestra::error audio::orchestra::api::Ds::abortStream() {
|
|||||||
|
|
||||||
void audio::orchestra::api::Ds::callbackEvent() {
|
void audio::orchestra::api::Ds::callbackEvent() {
|
||||||
ethread::setName("DS IO-" + m_name);
|
ethread::setName("DS IO-" + m_name);
|
||||||
if (m_state == audio::orchestra::state_stopped || m_state == audio::orchestra::state_stopping) {
|
if ( m_state == audio::orchestra::state::stopped
|
||||||
|
|| m_state == audio::orchestra::state::stopping) {
|
||||||
Sleep(50); // sleep 50 milliseconds
|
Sleep(50); // sleep 50 milliseconds
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check if we were draining the stream and signal is finished.
|
// Check if we were draining the stream and signal is finished.
|
||||||
if (m_private->drainCounter > m_nBuffers + 2) {
|
if (m_private->drainCounter > m_nBuffers + 2) {
|
||||||
m_state = audio::orchestra::state_stopping;
|
m_state = audio::orchestra::state::stopping;
|
||||||
if (m_private->internalDrain == false) {
|
if (m_private->internalDrain == false) {
|
||||||
SetEvent(m_private->condition);
|
SetEvent(m_private->condition);
|
||||||
} else {
|
} else {
|
||||||
@@ -1011,15 +1008,15 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
// draining stream.
|
// draining stream.
|
||||||
if (m_private->drainCounter == 0) {
|
if (m_private->drainCounter == 0) {
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<audio::orchestra::status> status;
|
etk::Vector<audio::orchestra::status> status;
|
||||||
if ( m_mode != audio::orchestra::mode_input
|
if ( m_mode != audio::orchestra::mode_input
|
||||||
&& m_private->xrun[0] == true) {
|
&& m_private->xrun[0] == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
if ( m_mode != audio::orchestra::mode_output
|
if ( m_mode != audio::orchestra::mode_output
|
||||||
&& m_private->xrun[1] == true) {
|
&& m_private->xrun[1] == true) {
|
||||||
status.push_back(audio::orchestra::status_overflow);
|
status.pushBack(audio::orchestra::status::overflow);
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
||||||
@@ -1029,7 +1026,7 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
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;
|
||||||
abortStream();
|
abortStream();
|
||||||
return;
|
return;
|
||||||
@@ -1042,8 +1039,8 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
DWORD currentWritePointer, safeWritePointer;
|
DWORD currentWritePointer, safeWritePointer;
|
||||||
DWORD currentReadPointer, safeReadPointer;
|
DWORD currentReadPointer, safeReadPointer;
|
||||||
UINT nextWritePointer;
|
UINT nextWritePointer;
|
||||||
LPVOID buffer1 = nullptr;
|
LPVOID buffer1 = null;
|
||||||
LPVOID buffer2 = nullptr;
|
LPVOID buffer2 = null;
|
||||||
DWORD bufferSize1 = 0;
|
DWORD bufferSize1 = 0;
|
||||||
DWORD bufferSize2 = 0;
|
DWORD bufferSize2 = 0;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
@@ -1066,23 +1063,23 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) m_private->buffer[0];
|
||||||
LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) m_private->buffer[1];
|
||||||
DWORD startSafeWritePointer, startSafeReadPointer;
|
DWORD startSafeWritePointer, startSafeReadPointer;
|
||||||
result = dsWriteBuffer->GetCurrentPosition(nullptr, &startSafeWritePointer);
|
result = dsWriteBuffer->GetCurrentPosition(null, &startSafeWritePointer);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": getting current write position!");
|
ATA_ERROR(getErrorString(result) << ": getting current write position!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = dsCaptureBuffer->GetCurrentPosition(nullptr, &startSafeReadPointer);
|
result = dsCaptureBuffer->GetCurrentPosition(null, &startSafeReadPointer);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": getting current read position!");
|
ATA_ERROR(getErrorString(result) << ": getting current read position!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
result = dsWriteBuffer->GetCurrentPosition(nullptr, &safeWritePointer);
|
result = dsWriteBuffer->GetCurrentPosition(null, &safeWritePointer);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": getting current write position!");
|
ATA_ERROR(getErrorString(result) << ": getting current write position!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = dsCaptureBuffer->GetCurrentPosition(nullptr, &safeReadPointer);
|
result = dsCaptureBuffer->GetCurrentPosition(null, &safeReadPointer);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR(getErrorString(result) << ": getting current read position!");
|
ATA_ERROR(getErrorString(result) << ": getting current read position!");
|
||||||
return;
|
return;
|
||||||
@@ -1156,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;
|
||||||
}
|
}
|
||||||
@@ -1203,7 +1200,7 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
}
|
}
|
||||||
// Copy our buffer into the DS buffer
|
// Copy our buffer into the DS buffer
|
||||||
CopyMemory(buffer1, buffer, bufferSize1);
|
CopyMemory(buffer1, buffer, bufferSize1);
|
||||||
if (buffer2 != nullptr) {
|
if (buffer2 != null) {
|
||||||
CopyMemory(buffer2, buffer+bufferSize1, bufferSize2);
|
CopyMemory(buffer2, buffer+bufferSize1, bufferSize2);
|
||||||
}
|
}
|
||||||
// Update our buffer offset and unlock sound buffer
|
// Update our buffer offset and unlock sound buffer
|
||||||
@@ -1321,12 +1318,12 @@ void audio::orchestra::api::Ds::callbackEvent() {
|
|||||||
if (m_duplexPrerollBytes <= 0) {
|
if (m_duplexPrerollBytes <= 0) {
|
||||||
// Copy our buffer into the DS buffer
|
// Copy our buffer into the DS buffer
|
||||||
CopyMemory(buffer, buffer1, bufferSize1);
|
CopyMemory(buffer, buffer1, bufferSize1);
|
||||||
if (buffer2 != nullptr) {
|
if (buffer2 != null) {
|
||||||
CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
|
CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memset(buffer, 0, bufferSize1);
|
memset(buffer, 0, bufferSize1);
|
||||||
if (buffer2 != nullptr) {
|
if (buffer2 != null) {
|
||||||
memset(buffer + bufferSize1, 0, bufferSize2);
|
memset(buffer + bufferSize1, 0, bufferSize2);
|
||||||
}
|
}
|
||||||
m_duplexPrerollBytes -= bufferSize1 + bufferSize2;
|
m_duplexPrerollBytes -= bufferSize1 + bufferSize2;
|
||||||
|
@@ -13,12 +13,12 @@ namespace audio {
|
|||||||
class DsPrivate;
|
class DsPrivate;
|
||||||
class Ds: public audio::orchestra::Api {
|
class Ds: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Ds();
|
Ds();
|
||||||
virtual ~Ds();
|
virtual ~Ds();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_ds;
|
return audio::orchestra::typeDs;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -34,7 +34,7 @@ namespace audio {
|
|||||||
void callbackEvent();
|
void callbackEvent();
|
||||||
private:
|
private:
|
||||||
static void dsCallbackEvent(void *_userData);
|
static void dsCallbackEvent(void *_userData);
|
||||||
std::shared_ptr<DsPrivate> m_private;
|
ememory::SharedPtr<DsPrivate> m_private;
|
||||||
bool m_coInitialized;
|
bool m_coInitialized;
|
||||||
bool m_buffersRolling;
|
bool m_buffersRolling;
|
||||||
long m_duplexPrerollBytes;
|
long m_duplexPrerollBytes;
|
@@ -6,14 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(ORCHESTRA_BUILD_DUMMY)
|
#if defined(ORCHESTRA_BUILD_DUMMY)
|
||||||
#include <audio/orchestra/api/Dummy.h>
|
#include <audio/orchestra/api/Dummy.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
|
||||||
#undef __class__
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Dummy::create() {
|
||||||
#define __class__ "api::Dummy"
|
return ememory::SharedPtr<audio::orchestra::api::Dummy>(ETK_NEW(audio::orchestra::api::Dummy));
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Dummy::create() {
|
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Dummy());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -8,18 +8,18 @@
|
|||||||
|
|
||||||
#ifdef ORCHESTRA_BUILD_DUMMY
|
#ifdef ORCHESTRA_BUILD_DUMMY
|
||||||
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
namespace api {
|
namespace api {
|
||||||
class Dummy: public audio::orchestra::Api {
|
class Dummy: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Dummy();
|
Dummy();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_dummy;
|
return audio::orchestra::typeDummy;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
@@ -7,20 +7,17 @@
|
|||||||
|
|
||||||
// must run before :
|
// must run before :
|
||||||
#if defined(ORCHESTRA_BUILD_JACK)
|
#if defined(ORCHESTRA_BUILD_JACK)
|
||||||
#include <unistd.h>
|
extern "C" {
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <iostream>
|
#include <string.h>
|
||||||
#include <audio/orchestra/Interface.h>
|
}
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
#include <string.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <ethread/tools.h>
|
#include <ethread/tools.hpp>
|
||||||
#include <audio/orchestra/api/Jack.h>
|
#include <audio/orchestra/api/Jack.hpp>
|
||||||
|
|
||||||
#undef __class__
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Jack::create() {
|
||||||
#define __class__ "api::Jack"
|
return ememory::SharedPtr<audio::orchestra::api::Jack>(ETK_NEW(audio::orchestra::api::Jack));
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Jack::create() {
|
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Jack());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,9 +52,9 @@ std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Jack::create() {
|
|||||||
// stream cannot be opened.
|
// stream cannot be opened.
|
||||||
|
|
||||||
#include <jack/jack.h>
|
#include <jack/jack.h>
|
||||||
#include <unistd.h>
|
extern "C" {
|
||||||
#include <cstdio>
|
#include <stdio.h>
|
||||||
|
}
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
@@ -66,9 +63,9 @@ namespace audio {
|
|||||||
public:
|
public:
|
||||||
jack_client_t *client;
|
jack_client_t *client;
|
||||||
jack_port_t **ports[2];
|
jack_port_t **ports[2];
|
||||||
std::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.
|
||||||
|
|
||||||
@@ -87,12 +84,12 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Jack::Jack() :
|
audio::orchestra::api::Jack::Jack() :
|
||||||
m_private(new audio::orchestra::api::JackPrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::JackPrivate)) {
|
||||||
// Nothing to do here.
|
// Nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Jack::~Jack() {
|
audio::orchestra::api::Jack::~Jack() {
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,23 +97,23 @@ audio::orchestra::api::Jack::~Jack() {
|
|||||||
uint32_t audio::orchestra::api::Jack::getDeviceCount() {
|
uint32_t audio::orchestra::api::Jack::getDeviceCount() {
|
||||||
// See if we can become a jack client.
|
// See if we can become a jack client.
|
||||||
jack_options_t options = (jack_options_t) (JackNoStartServer); //JackNullOption;
|
jack_options_t options = (jack_options_t) (JackNoStartServer); //JackNullOption;
|
||||||
jack_status_t *status = nullptr;
|
jack_status_t *status = null;
|
||||||
jack_client_t *client = jack_client_open("orchestraJackCount", options, status);
|
jack_client_t *client = jack_client_open("orchestraJackCount", options, status);
|
||||||
if (client == nullptr) {
|
if (client == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const char **ports;
|
const char **ports;
|
||||||
std::string port, previousPort;
|
etk::String port, previousPort;
|
||||||
uint32_t nChannels = 0, nDevices = 0;
|
uint32_t nChannels = 0, nDevices = 0;
|
||||||
ports = jack_get_ports(client, nullptr, nullptr, 0);
|
ports = jack_get_ports(client, null, null, 0);
|
||||||
if (ports) {
|
if (ports) {
|
||||||
// Parse the port names up to the first colon (:).
|
// Parse the port names up to the first colon (:).
|
||||||
size_t iColon = 0;
|
size_t iColon = 0;
|
||||||
do {
|
do {
|
||||||
port = (char *) ports[ nChannels ];
|
port = (char *) ports[ nChannels ];
|
||||||
iColon = port.find(":");
|
iColon = port.find(":");
|
||||||
if (iColon != std::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;
|
||||||
@@ -124,6 +121,7 @@ uint32_t audio::orchestra::api::Jack::getDeviceCount() {
|
|||||||
}
|
}
|
||||||
} while (ports[++nChannels]);
|
} while (ports[++nChannels]);
|
||||||
free(ports);
|
free(ports);
|
||||||
|
ports = null;
|
||||||
}
|
}
|
||||||
jack_client_close(client);
|
jack_client_close(client);
|
||||||
return nDevices*2;
|
return nDevices*2;
|
||||||
@@ -132,18 +130,18 @@ uint32_t audio::orchestra::api::Jack::getDeviceCount() {
|
|||||||
audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t _device) {
|
audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t _device) {
|
||||||
audio::orchestra::DeviceInfo info;
|
audio::orchestra::DeviceInfo info;
|
||||||
jack_options_t options = (jack_options_t) (JackNoStartServer); //JackNullOption
|
jack_options_t options = (jack_options_t) (JackNoStartServer); //JackNullOption
|
||||||
jack_status_t *status = nullptr;
|
jack_status_t *status = null;
|
||||||
jack_client_t *client = jack_client_open("orchestraJackInfo", options, status);
|
jack_client_t *client = jack_client_open("orchestraJackInfo", options, status);
|
||||||
if (client == nullptr) {
|
if (client == null) {
|
||||||
ATA_ERROR("Jack server not found or connection error!");
|
ATA_ERROR("Jack server not found or connection error!");
|
||||||
// TODO : audio::orchestra::error_warning;
|
// TODO : audio::orchestra::error_warning;
|
||||||
info.clear();
|
info.clear();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
const char **ports;
|
const char **ports;
|
||||||
std::string port, previousPort;
|
etk::String port, previousPort;
|
||||||
uint32_t nPorts = 0, nDevices = 0;
|
uint32_t nPorts = 0, nDevices = 0;
|
||||||
ports = jack_get_ports(client, nullptr, nullptr, 0);
|
ports = jack_get_ports(client, null, null, 0);
|
||||||
int32_t deviceID = _device/2;
|
int32_t deviceID = _device/2;
|
||||||
info.input = _device%2==0?true:false; // note that jack sens are inverted
|
info.input = _device%2==0?true:false; // note that jack sens are inverted
|
||||||
if (ports) {
|
if (ports) {
|
||||||
@@ -152,8 +150,8 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t
|
|||||||
do {
|
do {
|
||||||
port = (char *) ports[nPorts];
|
port = (char *) ports[nPorts];
|
||||||
iColon = port.find(":");
|
iColon = port.find(":");
|
||||||
if (iColon != std::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;
|
||||||
@@ -173,25 +171,25 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t
|
|||||||
}
|
}
|
||||||
// Get the current jack server sample rate.
|
// Get the current jack server sample rate.
|
||||||
info.sampleRates.clear();
|
info.sampleRates.clear();
|
||||||
info.sampleRates.push_back(jack_get_sample_rate(client));
|
info.sampleRates.pushBack(jack_get_sample_rate(client));
|
||||||
if (info.input == true) {
|
if (info.input == true) {
|
||||||
ports = jack_get_ports(client, info.name.c_str(), nullptr, JackPortIsOutput);
|
ports = jack_get_ports(client, info.name.c_str(), null, JackPortIsOutput);
|
||||||
if (ports) {
|
if (ports) {
|
||||||
int32_t iii=0;
|
int32_t iii=0;
|
||||||
while (ports[iii]) {
|
while (ports[iii]) {
|
||||||
ATA_ERROR(" ploppp='" << ports[iii] << "'");
|
ATA_ERROR(" ploppp='" << ports[iii] << "'");
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
iii++;
|
iii++;
|
||||||
}
|
}
|
||||||
free(ports);
|
free(ports);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ports = jack_get_ports(client, info.name.c_str(), nullptr, JackPortIsInput);
|
ports = jack_get_ports(client, info.name.c_str(), null, JackPortIsInput);
|
||||||
if (ports) {
|
if (ports) {
|
||||||
int32_t iii=0;
|
int32_t iii=0;
|
||||||
while (ports[iii]) {
|
while (ports[iii]) {
|
||||||
ATA_ERROR(" ploppp='" << ports[iii] << "'");
|
ATA_ERROR(" ploppp='" << ports[iii] << "'");
|
||||||
info.channels.push_back(audio::channel_unknow);
|
info.channels.pushBack(audio::channel_unknow);
|
||||||
iii++;
|
iii++;
|
||||||
}
|
}
|
||||||
free(ports);
|
free(ports);
|
||||||
@@ -205,7 +203,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Jack::getDeviceInfo(uint32_t
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
// Jack always uses 32-bit floats.
|
// Jack always uses 32-bit floats.
|
||||||
info.nativeFormats.push_back(audio::format_float);
|
info.nativeFormats.pushBack(audio::format_float);
|
||||||
// Jack doesn't provide default devices so we'll use the first available one.
|
// Jack doesn't provide default devices so we'll use the first available one.
|
||||||
if (deviceID == 0) {
|
if (deviceID == 0) {
|
||||||
info.isDefault = true;
|
info.isDefault = true;
|
||||||
@@ -226,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);
|
||||||
@@ -246,7 +235,7 @@ void audio::orchestra::api::Jack::jackShutdown(void* _userData) {
|
|||||||
if (myClass->isStreamRunning() == false) {
|
if (myClass->isStreamRunning() == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new std::thread(&audio::orchestra::api::Jack::jackCloseStream, _userData);
|
ETK_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!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,8 +264,8 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
|| ( _mode == audio::orchestra::mode_input
|
|| ( _mode == audio::orchestra::mode_input
|
||||||
&& 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 = null;
|
||||||
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);
|
||||||
@@ -290,19 +279,19 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
client = m_private->client;
|
client = m_private->client;
|
||||||
}
|
}
|
||||||
const char **ports;
|
const char **ports;
|
||||||
std::string port, previousPort, deviceName;
|
etk::String port, previousPort, deviceName;
|
||||||
uint32_t nPorts = 0, nDevices = 0;
|
uint32_t nPorts = 0, nDevices = 0;
|
||||||
int32_t deviceID = _device/2;
|
int32_t deviceID = _device/2;
|
||||||
bool isInput = _device%2==0?true:false;
|
bool isInput = _device%2==0?true:false;
|
||||||
ports = jack_get_ports(client, nullptr, nullptr, 0);
|
ports = jack_get_ports(client, null, null, 0);
|
||||||
if (ports) {
|
if (ports) {
|
||||||
// Parse the port names up to the first colon (:).
|
// Parse the port names up to the first colon (:).
|
||||||
size_t iColon = 0;
|
size_t iColon = 0;
|
||||||
do {
|
do {
|
||||||
port = (char *) ports[ nPorts ];
|
port = (char *) ports[ nPorts ];
|
||||||
iColon = port.find(":");
|
iColon = port.find(":");
|
||||||
if (iColon != std::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;
|
||||||
@@ -325,7 +314,7 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
if (_mode == audio::orchestra::mode_input) {
|
if (_mode == audio::orchestra::mode_input) {
|
||||||
flag = JackPortIsOutput;
|
flag = JackPortIsOutput;
|
||||||
}
|
}
|
||||||
ports = jack_get_ports(client, deviceName.c_str(), nullptr, flag);
|
ports = jack_get_ports(client, deviceName.c_str(), null, flag);
|
||||||
if (ports) {
|
if (ports) {
|
||||||
while (ports[ nChannels ]) {
|
while (ports[ nChannels ]) {
|
||||||
nChannels++;
|
nChannels++;
|
||||||
@@ -346,7 +335,7 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
m_sampleRate = jackRate;
|
m_sampleRate = jackRate;
|
||||||
// Get the latency of the JACK port.
|
// Get the latency of the JACK port.
|
||||||
ports = jack_get_ports(client, deviceName.c_str(), nullptr, flag);
|
ports = jack_get_ports(client, deviceName.c_str(), null, flag);
|
||||||
if (ports[ _firstChannel ]) {
|
if (ports[ _firstChannel ]) {
|
||||||
// Added by Ge Wang
|
// Added by Ge Wang
|
||||||
jack_latency_callback_mode_t cbmode = (_mode == audio::orchestra::mode_input ? JackCaptureLatency : JackPlaybackLatency);
|
jack_latency_callback_mode_t cbmode = (_mode == audio::orchestra::mode_input ? JackCaptureLatency : JackPlaybackLatency);
|
||||||
@@ -412,7 +401,7 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
bufferBytes *= *_bufferSize;
|
bufferBytes *= *_bufferSize;
|
||||||
if (m_deviceBuffer) free(m_deviceBuffer);
|
if (m_deviceBuffer) free(m_deviceBuffer);
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -420,13 +409,13 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Allocate memory for the Jack ports (channels) identifiers.
|
// Allocate memory for the Jack ports (channels) identifiers.
|
||||||
m_private->ports[modeToIdTable(_mode)] = (jack_port_t **) malloc (sizeof (jack_port_t *) * _channels);
|
m_private->ports[modeToIdTable(_mode)] = (jack_port_t **) malloc (sizeof (jack_port_t *) * _channels);
|
||||||
if (m_private->ports[modeToIdTable(_mode)] == nullptr) {
|
if (m_private->ports[modeToIdTable(_mode)] == null) {
|
||||||
ATA_ERROR("error allocating port memory.");
|
ATA_ERROR("error allocating port memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
m_device[modeToIdTable(_mode)] = _device;
|
m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_channelOffset[modeToIdTable(_mode)] = _firstChannel;
|
m_channelOffset[modeToIdTable(_mode)] = _firstChannel;
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
if ( m_mode == audio::orchestra::mode_output
|
if ( m_mode == audio::orchestra::mode_output
|
||||||
&& _mode == audio::orchestra::mode_input) {
|
&& _mode == audio::orchestra::mode_input) {
|
||||||
// We had already set up the stream for output.
|
// We had already set up the stream for output.
|
||||||
@@ -467,52 +456,52 @@ bool audio::orchestra::api::Jack::open(uint32_t _device,
|
|||||||
return true;
|
return true;
|
||||||
error:
|
error:
|
||||||
jack_client_close(m_private->client);
|
jack_client_close(m_private->client);
|
||||||
if (m_private->ports[0] != nullptr) {
|
if (m_private->ports[0] != null) {
|
||||||
free(m_private->ports[0]);
|
free(m_private->ports[0]);
|
||||||
m_private->ports[0] = nullptr;
|
m_private->ports[0] = null;
|
||||||
}
|
}
|
||||||
if (m_private->ports[1] != nullptr) {
|
if (m_private->ports[1] != null) {
|
||||||
free(m_private->ports[1]);
|
free(m_private->ports[1]);
|
||||||
m_private->ports[1] = nullptr;
|
m_private->ports[1] = null;
|
||||||
}
|
}
|
||||||
for (int32_t iii=0; iii<2; ++iii) {
|
for (int32_t iii=0; iii<2; ++iii) {
|
||||||
m_userBuffer[iii].clear();
|
m_userBuffer[iii].clear();
|
||||||
}
|
}
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Jack::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Jack::closeStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("no open stream to close!");
|
ATA_ERROR("no open stream to close!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
if (m_private != nullptr) {
|
if (m_private != null) {
|
||||||
if (m_state == audio::orchestra::state_running) {
|
if (m_state == audio::orchestra::state::running) {
|
||||||
jack_deactivate(m_private->client);
|
jack_deactivate(m_private->client);
|
||||||
}
|
}
|
||||||
jack_client_close(m_private->client);
|
jack_client_close(m_private->client);
|
||||||
}
|
}
|
||||||
if (m_private->ports[0] != nullptr) {
|
if (m_private->ports[0] != null) {
|
||||||
free(m_private->ports[0]);
|
free(m_private->ports[0]);
|
||||||
m_private->ports[0] = nullptr;
|
m_private->ports[0] = null;
|
||||||
}
|
}
|
||||||
if (m_private->ports[1] != nullptr) {
|
if (m_private->ports[1] != null) {
|
||||||
free(m_private->ports[1]);
|
free(m_private->ports[1]);
|
||||||
m_private->ports[1] = nullptr;
|
m_private->ports[1] = null;
|
||||||
}
|
}
|
||||||
for (int32_t i=0; i<2; i++) {
|
for (int32_t i=0; i<2; i++) {
|
||||||
m_userBuffer[i].clear();
|
m_userBuffer[i].clear();
|
||||||
}
|
}
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = null;
|
||||||
}
|
}
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +511,7 @@ enum audio::orchestra::error audio::orchestra::api::Jack::startStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -536,8 +525,8 @@ enum audio::orchestra::error audio::orchestra::api::Jack::startStream() {
|
|||||||
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) {
|
||||||
result = 1;
|
result = 1;
|
||||||
ports = jack_get_ports(m_private->client, m_private->deviceName[0].c_str(), nullptr, JackPortIsInput);
|
ports = jack_get_ports(m_private->client, m_private->deviceName[0].c_str(), null, JackPortIsInput);
|
||||||
if (ports == nullptr) {
|
if (ports == null) {
|
||||||
ATA_ERROR("error determining available JACK input ports!");
|
ATA_ERROR("error determining available JACK input ports!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
@@ -559,8 +548,8 @@ enum audio::orchestra::error audio::orchestra::api::Jack::startStream() {
|
|||||||
if ( m_mode == audio::orchestra::mode_input
|
if ( m_mode == audio::orchestra::mode_input
|
||||||
|| m_mode == audio::orchestra::mode_duplex) {
|
|| m_mode == audio::orchestra::mode_duplex) {
|
||||||
result = 1;
|
result = 1;
|
||||||
ports = jack_get_ports(m_private->client, m_private->deviceName[1].c_str(), nullptr, JackPortIsOutput);
|
ports = jack_get_ports(m_private->client, m_private->deviceName[1].c_str(), null, JackPortIsOutput);
|
||||||
if (ports == nullptr) {
|
if (ports == null) {
|
||||||
ATA_ERROR("error determining available JACK output ports!");
|
ATA_ERROR("error determining available JACK output ports!");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
@@ -580,7 +569,7 @@ enum audio::orchestra::error audio::orchestra::api::Jack::startStream() {
|
|||||||
}
|
}
|
||||||
m_private->drainCounter = 0;
|
m_private->drainCounter = 0;
|
||||||
m_private->internalDrain = false;
|
m_private->internalDrain = false;
|
||||||
m_state = audio::orchestra::state_running;
|
m_state = audio::orchestra::state::running;
|
||||||
unlock:
|
unlock:
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
@@ -592,7 +581,7 @@ enum audio::orchestra::error audio::orchestra::api::Jack::stopStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -600,12 +589,11 @@ 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;
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
m_private->m_semaphore.wait();
|
||||||
m_private->condition.wait(lck);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jack_deactivate(m_private->client);
|
jack_deactivate(m_private->client);
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +601,7 @@ enum audio::orchestra::error audio::orchestra::api::Jack::abortStream() {
|
|||||||
if (verifyStream() != audio::orchestra::error_none) {
|
if (verifyStream() != audio::orchestra::error_none) {
|
||||||
return audio::orchestra::error_fail;
|
return audio::orchestra::error_fail;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
@@ -621,23 +609,12 @@ 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) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -647,24 +624,24 @@ bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) {
|
|||||||
}
|
}
|
||||||
// Check if we were draining the stream and signal is finished.
|
// Check if we were draining the stream and signal is finished.
|
||||||
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 std::thread(jackStopStream, this);
|
ETK_NEW(ethread::Thread, [&](){stopStream();}, "Jack_stopStream");
|
||||||
} else {
|
} else {
|
||||||
m_private->condition.notify_one();
|
m_private->m_semaphore.post();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Invoke user callback first, to get fresh output data.
|
// Invoke user callback first, to get fresh output data.
|
||||||
if (m_private->drainCounter == 0) {
|
if (m_private->drainCounter == 0) {
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
if (m_mode != audio::orchestra::mode_input && m_private->xrun[0] == true) {
|
if (m_mode != audio::orchestra::mode_input && m_private->xrun[0] == true) {
|
||||||
status.push_back(audio::orchestra::status_underflow);
|
status.pushBack(audio::orchestra::status::underflow);
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
if (m_mode != audio::orchestra::mode_output && m_private->xrun[1] == true) {
|
if (m_mode != audio::orchestra::mode_output && m_private->xrun[1] == true) {
|
||||||
status.push_back(audio::orchestra::status_overflow);
|
status.pushBack(audio::orchestra::status::overflow);
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
|
||||||
@@ -674,9 +651,9 @@ bool audio::orchestra::api::Jack::callbackEvent(uint64_t _nframes) {
|
|||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
status);
|
status);
|
||||||
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 std::thread(jackStopStream, this);
|
ETK_NEW(ethread::Thread, [&](){stopStream();}, "Jack_stopStream2");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (cbReturnValue == 1) {
|
else if (cbReturnValue == 1) {
|
||||||
|
@@ -15,12 +15,12 @@ namespace audio {
|
|||||||
class JackPrivate;
|
class JackPrivate;
|
||||||
class Jack: public audio::orchestra::Api {
|
class Jack: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Jack();
|
Jack();
|
||||||
virtual ~Jack();
|
virtual ~Jack();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_jack;
|
return audio::orchestra::typeJack;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -36,11 +36,10 @@ 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:
|
||||||
std::shared_ptr<JackPrivate> m_private;
|
ememory::SharedPtr<JackPrivate> m_private;
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
@@ -8,22 +8,20 @@
|
|||||||
|
|
||||||
#if defined(ORCHESTRA_BUILD_PULSE)
|
#if defined(ORCHESTRA_BUILD_PULSE)
|
||||||
|
|
||||||
#include <unistd.h>
|
extern "C" {
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <stdio.h>
|
||||||
#include <audio/orchestra/debug.h>
|
}
|
||||||
|
#include <audio/orchestra/Interface.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.h>
|
#include <audio/orchestra/api/PulseDeviceList.hpp>
|
||||||
#include <audio/orchestra/api/PulseDeviceList.h>
|
#include <audio/orchestra/api/Pulse.hpp>
|
||||||
#include <audio/orchestra/api/Pulse.h>
|
|
||||||
|
|
||||||
#undef __class__
|
ememory::SharedPtr<audio::orchestra::Api> audio::orchestra::api::Pulse::create() {
|
||||||
#define __class__ "api::Pulse"
|
return ememory::SharedPtr<audio::orchestra::api::Pulse>(ETK_NEW(audio::orchestra::api::Pulse));
|
||||||
|
|
||||||
std::shared_ptr<audio::orchestra::Api> audio::orchestra::api::Pulse::create() {
|
|
||||||
return std::shared_ptr<audio::orchestra::Api>(new audio::orchestra::api::Pulse());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -56,9 +54,9 @@ namespace audio {
|
|||||||
class PulsePrivate {
|
class PulsePrivate {
|
||||||
public:
|
public:
|
||||||
pa_simple* handle;
|
pa_simple* handle;
|
||||||
std::shared_ptr<std::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),
|
||||||
@@ -71,19 +69,19 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio::orchestra::api::Pulse::Pulse() :
|
audio::orchestra::api::Pulse::Pulse() :
|
||||||
m_private(new audio::orchestra::api::PulsePrivate()) {
|
m_private(ETK_NEW(audio::orchestra::api::PulsePrivate)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::api::Pulse::~Pulse() {
|
audio::orchestra::api::Pulse::~Pulse() {
|
||||||
if (m_state != audio::orchestra::state_closed) {
|
if (m_state != audio::orchestra::state::closed) {
|
||||||
closeStream();
|
closeStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t audio::orchestra::api::Pulse::getDeviceCount() {
|
uint32_t audio::orchestra::api::Pulse::getDeviceCount() {
|
||||||
#if 1
|
#if 1
|
||||||
std::vector<audio::orchestra::DeviceInfo> list = audio::orchestra::api::pulse::getDeviceList();
|
etk::Vector<audio::orchestra::DeviceInfo> list = audio::orchestra::api::pulse::getDeviceList();
|
||||||
return list.size();
|
return list.size();
|
||||||
#else
|
#else
|
||||||
return 1;
|
return 1;
|
||||||
@@ -91,7 +89,7 @@ uint32_t audio::orchestra::api::Pulse::getDeviceCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio::orchestra::DeviceInfo audio::orchestra::api::Pulse::getDeviceInfo(uint32_t _device) {
|
audio::orchestra::DeviceInfo audio::orchestra::api::Pulse::getDeviceInfo(uint32_t _device) {
|
||||||
std::vector<audio::orchestra::DeviceInfo> list = audio::orchestra::api::pulse::getDeviceList();
|
etk::Vector<audio::orchestra::DeviceInfo> list = audio::orchestra::api::pulse::getDeviceList();
|
||||||
if (_device >= list.size()) {
|
if (_device >= list.size()) {
|
||||||
ATA_ERROR("Request device out of IDs:" << _device << " >= " << list.size());
|
ATA_ERROR("Request device out of IDs:" << _device << " >= " << list.size());
|
||||||
return audio::orchestra::DeviceInfo();
|
return audio::orchestra::DeviceInfo();
|
||||||
@@ -99,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);
|
||||||
@@ -114,41 +109,40 @@ void audio::orchestra::api::Pulse::callbackEvent() {
|
|||||||
enum audio::orchestra::error audio::orchestra::api::Pulse::closeStream() {
|
enum audio::orchestra::error audio::orchestra::api::Pulse::closeStream() {
|
||||||
m_private->threadRunning = false;
|
m_private->threadRunning = false;
|
||||||
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, null);
|
||||||
}
|
}
|
||||||
pa_simple_free(m_private->handle);
|
pa_simple_free(m_private->handle);
|
||||||
m_private->handle = nullptr;
|
m_private->handle = null;
|
||||||
m_userBuffer[0].clear();
|
m_userBuffer[0].clear();
|
||||||
m_userBuffer[1].clear();
|
m_userBuffer[1].clear();
|
||||||
m_state = audio::orchestra::state_closed;
|
m_state = audio::orchestra::state::closed;
|
||||||
m_mode = audio::orchestra::mode_unknow;
|
m_mode = audio::orchestra::mode_unknow;
|
||||||
return audio::orchestra::error_none;
|
return audio::orchestra::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
std::unique_lock<std::mutex> 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
ATA_ERROR("the stream is closed ... this shouldn't happen!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
audio::Time streamTime = getStreamTime();
|
audio::Time streamTime = getStreamTime();
|
||||||
std::vector<enum audio::orchestra::status> status;
|
etk::Vector<enum audio::orchestra::status> status;
|
||||||
int32_t doStopStream = m_callback(&m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)][0],
|
int32_t doStopStream = m_callback(&m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_input)][0],
|
||||||
streamTime,
|
streamTime,
|
||||||
&m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)][0],
|
&m_userBuffer[audio::orchestra::modeToIdTable(audio::orchestra::mode_output)][0],
|
||||||
@@ -162,8 +156,8 @@ void audio::orchestra::api::Pulse::callbackEventOneCycle() {
|
|||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
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;
|
||||||
@@ -197,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();
|
||||||
@@ -210,71 +204,71 @@ unlock:
|
|||||||
enum audio::orchestra::error audio::orchestra::api::Pulse::startStream() {
|
enum audio::orchestra::error audio::orchestra::api::Pulse::startStream() {
|
||||||
// TODO : Check return ...
|
// TODO : Check return ...
|
||||||
audio::orchestra::Api::startStream();
|
audio::orchestra::Api::startStream();
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is not open!");
|
ATA_ERROR("the stream is not open!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Pulse::stopStream() {
|
enum audio::orchestra::error audio::orchestra::api::Pulse::stopStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is not open!");
|
ATA_ERROR("the stream is not open!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
if ( m_private != nullptr
|
if ( m_private != null
|
||||||
&& m_private->handle != nullptr
|
&& m_private->handle != null
|
||||||
&& m_mode == audio::orchestra::mode_output) {
|
&& m_mode == audio::orchestra::mode_output) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum audio::orchestra::error audio::orchestra::api::Pulse::abortStream() {
|
enum audio::orchestra::error audio::orchestra::api::Pulse::abortStream() {
|
||||||
if (m_state == audio::orchestra::state_closed) {
|
if (m_state == audio::orchestra::state::closed) {
|
||||||
ATA_ERROR("the stream is not open!");
|
ATA_ERROR("the stream is not open!");
|
||||||
return audio::orchestra::error_invalidUse;
|
return audio::orchestra::error_invalidUse;
|
||||||
}
|
}
|
||||||
if (m_state == audio::orchestra::state_stopped) {
|
if (m_state == audio::orchestra::state::stopped) {
|
||||||
ATA_ERROR("the stream is already stopped!");
|
ATA_ERROR("the stream is already stopped!");
|
||||||
return audio::orchestra::error_warning;
|
return audio::orchestra::error_warning;
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
if ( m_private != nullptr
|
if ( m_private != null
|
||||||
&& m_private->handle != nullptr
|
&& m_private->handle != null
|
||||||
&& m_mode == audio::orchestra::mode_output) {
|
&& m_mode == audio::orchestra::mode_output) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +353,7 @@ bool audio::orchestra::api::Pulse::open(uint32_t _device,
|
|||||||
bufferBytes *= *_bufferSize;
|
bufferBytes *= *_bufferSize;
|
||||||
if (m_deviceBuffer) free(m_deviceBuffer);
|
if (m_deviceBuffer) free(m_deviceBuffer);
|
||||||
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
m_deviceBuffer = (char *) calloc(bufferBytes, 1);
|
||||||
if (m_deviceBuffer == nullptr) {
|
if (m_deviceBuffer == null) {
|
||||||
ATA_ERROR("error allocating device buffer memory.");
|
ATA_ERROR("error allocating device buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -373,15 +367,15 @@ bool audio::orchestra::api::Pulse::open(uint32_t _device,
|
|||||||
int32_t error;
|
int32_t error;
|
||||||
switch (_mode) {
|
switch (_mode) {
|
||||||
case audio::orchestra::mode_input:
|
case audio::orchestra::mode_input:
|
||||||
m_private->handle = pa_simple_new(nullptr, "orchestra", PA_STREAM_RECORD, nullptr, "Record", &ss, nullptr, nullptr, &error);
|
m_private->handle = pa_simple_new(null, "orchestra", PA_STREAM_RECORD, null, "Record", &ss, null, null, &error);
|
||||||
if (m_private->handle == nullptr) {
|
if (m_private->handle == null) {
|
||||||
ATA_ERROR("error connecting input to PulseAudio server.");
|
ATA_ERROR("error connecting input to PulseAudio server.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case audio::orchestra::mode_output:
|
case audio::orchestra::mode_output:
|
||||||
m_private->handle = pa_simple_new(nullptr, "orchestra", PA_STREAM_PLAYBACK, nullptr, "Playback", &ss, nullptr, nullptr, &error);
|
m_private->handle = pa_simple_new(null, "orchestra", PA_STREAM_PLAYBACK, null, "Playback", &ss, null, null, &error);
|
||||||
if (m_private->handle == nullptr) {
|
if (m_private->handle == null) {
|
||||||
ATA_ERROR("error connecting output to PulseAudio server.");
|
ATA_ERROR("error connecting output to PulseAudio server.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -396,13 +390,13 @@ 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 = std::make_shared<std::thread>(&pulseaudio_callback, this);
|
m_private->thread = ememory::makeShared<ethread::Thread>([&](){callbackEvent();}, "pulseCallback");
|
||||||
if (m_private->thread == nullptr) {
|
if (m_private->thread == null) {
|
||||||
ATA_ERROR("error creating thread.");
|
ATA_ERROR("error creating thread.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_state = audio::orchestra::state_stopped;
|
m_state = audio::orchestra::state::stopped;
|
||||||
return true;
|
return true;
|
||||||
error:
|
error:
|
||||||
for (int32_t iii=0; iii<2; ++iii) {
|
for (int32_t iii=0; iii<2; ++iii) {
|
||||||
|
@@ -13,12 +13,12 @@ namespace audio {
|
|||||||
class PulsePrivate;
|
class PulsePrivate;
|
||||||
class Pulse: public audio::orchestra::Api {
|
class Pulse: public audio::orchestra::Api {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<audio::orchestra::Api> create();
|
static ememory::SharedPtr<audio::orchestra::Api> create();
|
||||||
public:
|
public:
|
||||||
Pulse();
|
Pulse();
|
||||||
virtual ~Pulse();
|
virtual ~Pulse();
|
||||||
const std::string& getCurrentApi() {
|
const etk::String& getCurrentApi() {
|
||||||
return audio::orchestra::type_pulse;
|
return audio::orchestra::typePulse;
|
||||||
}
|
}
|
||||||
uint32_t getDeviceCount();
|
uint32_t getDeviceCount();
|
||||||
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
|
||||||
@@ -33,8 +33,8 @@ namespace audio {
|
|||||||
void callbackEventOneCycle();
|
void callbackEventOneCycle();
|
||||||
void callbackEvent();
|
void callbackEvent();
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<PulsePrivate> m_private;
|
ememory::SharedPtr<PulsePrivate> m_private;
|
||||||
std::vector<audio::orchestra::DeviceInfo> m_devices;
|
etk::Vector<audio::orchestra::DeviceInfo> m_devices;
|
||||||
void saveDeviceInfo();
|
void saveDeviceInfo();
|
||||||
bool open(uint32_t _device,
|
bool open(uint32_t _device,
|
||||||
audio::orchestra::mode _mode,
|
audio::orchestra::mode _mode,
|
@@ -6,16 +6,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(ORCHESTRA_BUILD_PULSE)
|
#if defined(ORCHESTRA_BUILD_PULSE)
|
||||||
|
extern "C" {
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
}
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
#include <audio/orchestra/api/PulseDeviceList.h>
|
#include <audio/orchestra/api/PulseDeviceList.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <audio/Time.h>
|
#include <audio/Time.hpp>
|
||||||
#include <audio/Duration.h>
|
#include <audio/Duration.hpp>
|
||||||
#include <audio/format.h>
|
#include <audio/format.hpp>
|
||||||
#include <etk/stdTools.h>
|
#include <etk/stdTools.hpp>
|
||||||
|
|
||||||
// This callback gets called when our context changes state. We really only
|
// This callback gets called when our context changes state. We really only
|
||||||
// care about when it's ready or if it has failed
|
// care about when it's ready or if it has failed
|
||||||
@@ -105,101 +106,101 @@ static audio::format getFormatFromPulseFormat(enum pa_sample_format _format) {
|
|||||||
return audio::format_unknow;
|
return audio::format_unknow;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<audio::channel> getChannelOrderFromPulseChannel(const struct pa_channel_map& _map) {
|
static etk::Vector<audio::channel> getChannelOrderFromPulseChannel(const struct pa_channel_map& _map) {
|
||||||
std::vector<audio::channel> out;
|
etk::Vector<audio::channel> out;
|
||||||
|
|
||||||
for (int32_t iii=0; iii<_map.channels; ++iii) {
|
for (int32_t iii=0; iii<_map.channels; ++iii) {
|
||||||
switch(_map.map[iii]) {
|
switch(_map.map[iii]) {
|
||||||
default:
|
default:
|
||||||
case PA_CHANNEL_POSITION_MAX:
|
case PA_CHANNEL_POSITION_MAX:
|
||||||
case PA_CHANNEL_POSITION_INVALID:
|
case PA_CHANNEL_POSITION_INVALID:
|
||||||
out.push_back(audio::channel_unknow);
|
out.pushBack(audio::channel_unknow);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_MONO:
|
case PA_CHANNEL_POSITION_MONO:
|
||||||
case PA_CHANNEL_POSITION_FRONT_CENTER:
|
case PA_CHANNEL_POSITION_FRONT_CENTER:
|
||||||
out.push_back(audio::channel_frontCenter);
|
out.pushBack(audio::channel_frontCenter);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_FRONT_LEFT:
|
case PA_CHANNEL_POSITION_FRONT_LEFT:
|
||||||
out.push_back(audio::channel_frontLeft);
|
out.pushBack(audio::channel_frontLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_FRONT_RIGHT:
|
case PA_CHANNEL_POSITION_FRONT_RIGHT:
|
||||||
out.push_back(audio::channel_frontRight);
|
out.pushBack(audio::channel_frontRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_REAR_CENTER:
|
case PA_CHANNEL_POSITION_REAR_CENTER:
|
||||||
out.push_back(audio::channel_rearCenter);
|
out.pushBack(audio::channel_rearCenter);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_REAR_LEFT:
|
case PA_CHANNEL_POSITION_REAR_LEFT:
|
||||||
out.push_back(audio::channel_rearLeft);
|
out.pushBack(audio::channel_rearLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_REAR_RIGHT:
|
case PA_CHANNEL_POSITION_REAR_RIGHT:
|
||||||
out.push_back(audio::channel_rearRight);
|
out.pushBack(audio::channel_rearRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_LFE:
|
case PA_CHANNEL_POSITION_LFE:
|
||||||
out.push_back(audio::channel_lfe);
|
out.pushBack(audio::channel_lfe);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
|
case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
|
||||||
out.push_back(audio::channel_centerLeft);
|
out.pushBack(audio::channel_centerLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
|
case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
|
||||||
out.push_back(audio::channel_centerRight);
|
out.pushBack(audio::channel_centerRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_SIDE_LEFT:
|
case PA_CHANNEL_POSITION_SIDE_LEFT:
|
||||||
out.push_back(audio::channel_topCenterLeft);
|
out.pushBack(audio::channel_topCenterLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_SIDE_RIGHT:
|
case PA_CHANNEL_POSITION_SIDE_RIGHT:
|
||||||
out.push_back(audio::channel_topCenterRight);
|
out.pushBack(audio::channel_topCenterRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_CENTER:
|
case PA_CHANNEL_POSITION_TOP_CENTER:
|
||||||
case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:
|
case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:
|
||||||
out.push_back(audio::channel_topFrontCenter);
|
out.pushBack(audio::channel_topFrontCenter);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
|
case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
|
||||||
out.push_back(audio::channel_topFrontLeft);
|
out.pushBack(audio::channel_topFrontLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
|
case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
|
||||||
out.push_back(audio::channel_topFrontRight);
|
out.pushBack(audio::channel_topFrontRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
|
case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
|
||||||
out.push_back(audio::channel_topRearLeft);
|
out.pushBack(audio::channel_topRearLeft);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
|
case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
|
||||||
out.push_back(audio::channel_topRearRight);
|
out.pushBack(audio::channel_topRearRight);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_TOP_REAR_CENTER:
|
case PA_CHANNEL_POSITION_TOP_REAR_CENTER:
|
||||||
out.push_back(audio::channel_topRearCenter);
|
out.pushBack(audio::channel_topRearCenter);
|
||||||
break;
|
break;
|
||||||
case PA_CHANNEL_POSITION_AUX0: out.push_back(audio::channel_aux0); break;
|
case PA_CHANNEL_POSITION_AUX0: out.pushBack(audio::channel_aux0); break;
|
||||||
case PA_CHANNEL_POSITION_AUX1: out.push_back(audio::channel_aux1); break;
|
case PA_CHANNEL_POSITION_AUX1: out.pushBack(audio::channel_aux1); break;
|
||||||
case PA_CHANNEL_POSITION_AUX2: out.push_back(audio::channel_aux2); break;
|
case PA_CHANNEL_POSITION_AUX2: out.pushBack(audio::channel_aux2); break;
|
||||||
case PA_CHANNEL_POSITION_AUX3: out.push_back(audio::channel_aux3); break;
|
case PA_CHANNEL_POSITION_AUX3: out.pushBack(audio::channel_aux3); break;
|
||||||
case PA_CHANNEL_POSITION_AUX4: out.push_back(audio::channel_aux4); break;
|
case PA_CHANNEL_POSITION_AUX4: out.pushBack(audio::channel_aux4); break;
|
||||||
case PA_CHANNEL_POSITION_AUX5: out.push_back(audio::channel_aux5); break;
|
case PA_CHANNEL_POSITION_AUX5: out.pushBack(audio::channel_aux5); break;
|
||||||
case PA_CHANNEL_POSITION_AUX6: out.push_back(audio::channel_aux6); break;
|
case PA_CHANNEL_POSITION_AUX6: out.pushBack(audio::channel_aux6); break;
|
||||||
case PA_CHANNEL_POSITION_AUX7: out.push_back(audio::channel_aux7); break;
|
case PA_CHANNEL_POSITION_AUX7: out.pushBack(audio::channel_aux7); break;
|
||||||
case PA_CHANNEL_POSITION_AUX8: out.push_back(audio::channel_aux8); break;
|
case PA_CHANNEL_POSITION_AUX8: out.pushBack(audio::channel_aux8); break;
|
||||||
case PA_CHANNEL_POSITION_AUX9: out.push_back(audio::channel_aux9); break;
|
case PA_CHANNEL_POSITION_AUX9: out.pushBack(audio::channel_aux9); break;
|
||||||
case PA_CHANNEL_POSITION_AUX10: out.push_back(audio::channel_aux10); break;
|
case PA_CHANNEL_POSITION_AUX10: out.pushBack(audio::channel_aux10); break;
|
||||||
case PA_CHANNEL_POSITION_AUX11: out.push_back(audio::channel_aux11); break;
|
case PA_CHANNEL_POSITION_AUX11: out.pushBack(audio::channel_aux11); break;
|
||||||
case PA_CHANNEL_POSITION_AUX12: out.push_back(audio::channel_aux12); break;
|
case PA_CHANNEL_POSITION_AUX12: out.pushBack(audio::channel_aux12); break;
|
||||||
case PA_CHANNEL_POSITION_AUX13: out.push_back(audio::channel_aux13); break;
|
case PA_CHANNEL_POSITION_AUX13: out.pushBack(audio::channel_aux13); break;
|
||||||
case PA_CHANNEL_POSITION_AUX14: out.push_back(audio::channel_aux14); break;
|
case PA_CHANNEL_POSITION_AUX14: out.pushBack(audio::channel_aux14); break;
|
||||||
case PA_CHANNEL_POSITION_AUX15: out.push_back(audio::channel_aux15); break;
|
case PA_CHANNEL_POSITION_AUX15: out.pushBack(audio::channel_aux15); break;
|
||||||
case PA_CHANNEL_POSITION_AUX16: out.push_back(audio::channel_aux16); break;
|
case PA_CHANNEL_POSITION_AUX16: out.pushBack(audio::channel_aux16); break;
|
||||||
case PA_CHANNEL_POSITION_AUX17: out.push_back(audio::channel_aux17); break;
|
case PA_CHANNEL_POSITION_AUX17: out.pushBack(audio::channel_aux17); break;
|
||||||
case PA_CHANNEL_POSITION_AUX18: out.push_back(audio::channel_aux18); break;
|
case PA_CHANNEL_POSITION_AUX18: out.pushBack(audio::channel_aux18); break;
|
||||||
case PA_CHANNEL_POSITION_AUX19: out.push_back(audio::channel_aux19); break;
|
case PA_CHANNEL_POSITION_AUX19: out.pushBack(audio::channel_aux19); break;
|
||||||
case PA_CHANNEL_POSITION_AUX20: out.push_back(audio::channel_aux20); break;
|
case PA_CHANNEL_POSITION_AUX20: out.pushBack(audio::channel_aux20); break;
|
||||||
case PA_CHANNEL_POSITION_AUX21: out.push_back(audio::channel_aux21); break;
|
case PA_CHANNEL_POSITION_AUX21: out.pushBack(audio::channel_aux21); break;
|
||||||
case PA_CHANNEL_POSITION_AUX22: out.push_back(audio::channel_aux22); break;
|
case PA_CHANNEL_POSITION_AUX22: out.pushBack(audio::channel_aux22); break;
|
||||||
case PA_CHANNEL_POSITION_AUX23: out.push_back(audio::channel_aux23); break;
|
case PA_CHANNEL_POSITION_AUX23: out.pushBack(audio::channel_aux23); break;
|
||||||
case PA_CHANNEL_POSITION_AUX24: out.push_back(audio::channel_aux24); break;
|
case PA_CHANNEL_POSITION_AUX24: out.pushBack(audio::channel_aux24); break;
|
||||||
case PA_CHANNEL_POSITION_AUX25: out.push_back(audio::channel_aux25); break;
|
case PA_CHANNEL_POSITION_AUX25: out.pushBack(audio::channel_aux25); break;
|
||||||
case PA_CHANNEL_POSITION_AUX26: out.push_back(audio::channel_aux26); break;
|
case PA_CHANNEL_POSITION_AUX26: out.pushBack(audio::channel_aux26); break;
|
||||||
case PA_CHANNEL_POSITION_AUX27: out.push_back(audio::channel_aux27); break;
|
case PA_CHANNEL_POSITION_AUX27: out.pushBack(audio::channel_aux27); break;
|
||||||
case PA_CHANNEL_POSITION_AUX28: out.push_back(audio::channel_aux28); break;
|
case PA_CHANNEL_POSITION_AUX28: out.pushBack(audio::channel_aux28); break;
|
||||||
case PA_CHANNEL_POSITION_AUX29: out.push_back(audio::channel_aux29); break;
|
case PA_CHANNEL_POSITION_AUX29: out.pushBack(audio::channel_aux29); break;
|
||||||
case PA_CHANNEL_POSITION_AUX30: out.push_back(audio::channel_aux30); break;
|
case PA_CHANNEL_POSITION_AUX30: out.pushBack(audio::channel_aux30); break;
|
||||||
case PA_CHANNEL_POSITION_AUX31: out.push_back(audio::channel_aux31); break;
|
case PA_CHANNEL_POSITION_AUX31: out.pushBack(audio::channel_aux31); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +208,7 @@ static std::vector<audio::channel> getChannelOrderFromPulseChannel(const struct
|
|||||||
}
|
}
|
||||||
// Callback on getting data from pulseaudio:
|
// Callback on getting data from pulseaudio:
|
||||||
static void callbackGetSinkList(pa_context* _contex, const pa_sink_info* _info, int _eol, void* _userdata) {
|
static void callbackGetSinkList(pa_context* _contex, const pa_sink_info* _info, int _eol, void* _userdata) {
|
||||||
std::vector<audio::orchestra::DeviceInfo>* list = static_cast<std::vector<audio::orchestra::DeviceInfo>*>(_userdata);
|
etk::Vector<audio::orchestra::DeviceInfo>* list = static_cast<etk::Vector<audio::orchestra::DeviceInfo>*>(_userdata);
|
||||||
// If eol is set to a positive number, you're at the end of the list
|
// If eol is set to a positive number, you're at the end of the list
|
||||||
if (_eol > 0) {
|
if (_eol > 0) {
|
||||||
return;
|
return;
|
||||||
@@ -217,17 +218,17 @@ static void callbackGetSinkList(pa_context* _contex, const pa_sink_info* _info,
|
|||||||
info.input = false;
|
info.input = false;
|
||||||
info.name = _info->name;
|
info.name = _info->name;
|
||||||
info.desc = _info->description;
|
info.desc = _info->description;
|
||||||
info.sampleRates.push_back(_info->sample_spec.rate);
|
info.sampleRates.pushBack(_info->sample_spec.rate);
|
||||||
info.nativeFormats.push_back(getFormatFromPulseFormat(_info->sample_spec.format));
|
info.nativeFormats.pushBack(getFormatFromPulseFormat(_info->sample_spec.format));
|
||||||
info.channels = getChannelOrderFromPulseChannel(_info->channel_map);
|
info.channels = getChannelOrderFromPulseChannel(_info->channel_map);
|
||||||
ATA_VERBOSE("plop=" << _info->index << " " << _info->name);
|
ATA_VERBOSE("plop=" << _info->index << " " << _info->name);
|
||||||
//ATA_DEBUG(" ports=" << _info->n_ports);
|
//ATA_DEBUG(" ports=" << _info->n_ports);
|
||||||
list->push_back(info);
|
list->pushBack(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// allback to get data from pulseaudio:
|
// allback to get data from pulseaudio:
|
||||||
static void callbackGetSourceList(pa_context* _contex, const pa_source_info* _info, int _eol, void* _userdata) {
|
static void callbackGetSourceList(pa_context* _contex, const pa_source_info* _info, int _eol, void* _userdata) {
|
||||||
std::vector<audio::orchestra::DeviceInfo>* list = static_cast<std::vector<audio::orchestra::DeviceInfo>*>(_userdata);
|
etk::Vector<audio::orchestra::DeviceInfo>* list = static_cast<etk::Vector<audio::orchestra::DeviceInfo>*>(_userdata);
|
||||||
if (_eol > 0) {
|
if (_eol > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -236,18 +237,18 @@ static void callbackGetSourceList(pa_context* _contex, const pa_source_info* _in
|
|||||||
info.input = true;
|
info.input = true;
|
||||||
info.name = _info->name;
|
info.name = _info->name;
|
||||||
info.desc = _info->description;
|
info.desc = _info->description;
|
||||||
info.sampleRates.push_back(_info->sample_spec.rate);
|
info.sampleRates.pushBack(_info->sample_spec.rate);
|
||||||
info.nativeFormats.push_back(getFormatFromPulseFormat(_info->sample_spec.format));
|
info.nativeFormats.pushBack(getFormatFromPulseFormat(_info->sample_spec.format));
|
||||||
info.channels = getChannelOrderFromPulseChannel(_info->channel_map);
|
info.channels = getChannelOrderFromPulseChannel(_info->channel_map);
|
||||||
ATA_VERBOSE("plop=" << _info->index << " " << _info->name);
|
ATA_VERBOSE("plop=" << _info->index << " " << _info->name);
|
||||||
list->push_back(info);
|
list->pushBack(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// to not update all the time ...
|
// to not update all the time ...
|
||||||
static std::vector<audio::orchestra::DeviceInfo> pulseAudioListOfDevice;
|
static etk::Vector<audio::orchestra::DeviceInfo> pulseAudioListOfDevice;
|
||||||
static audio::Time pulseAudioListOfDeviceTime;
|
static audio::Time pulseAudioListOfDeviceTime;
|
||||||
|
|
||||||
std::vector<audio::orchestra::DeviceInfo> audio::orchestra::api::pulse::getDeviceList() {
|
etk::Vector<audio::orchestra::DeviceInfo> audio::orchestra::api::pulse::getDeviceList() {
|
||||||
audio::Duration delta = audio::Time::now() - pulseAudioListOfDeviceTime;
|
audio::Duration delta = audio::Time::now() - pulseAudioListOfDeviceTime;
|
||||||
if (delta < audio::Duration(30,0)) {
|
if (delta < audio::Duration(30,0)) {
|
||||||
return pulseAudioListOfDevice;
|
return pulseAudioListOfDevice;
|
||||||
@@ -258,7 +259,7 @@ std::vector<audio::orchestra::DeviceInfo> audio::orchestra::api::pulse::getDevic
|
|||||||
pa_operation* pulseAudioOperation;
|
pa_operation* pulseAudioOperation;
|
||||||
pa_context* pulseAudioContex;
|
pa_context* pulseAudioContex;
|
||||||
pa_context_flags_t pulseAudioFlags = PA_CONTEXT_NOAUTOSPAWN;
|
pa_context_flags_t pulseAudioFlags = PA_CONTEXT_NOAUTOSPAWN;
|
||||||
std::vector<audio::orchestra::DeviceInfo>& out = pulseAudioListOfDevice;
|
etk::Vector<audio::orchestra::DeviceInfo>& out = pulseAudioListOfDevice;
|
||||||
out.clear();
|
out.clear();
|
||||||
// We'll need these state variables to keep track of our requests
|
// We'll need these state variables to keep track of our requests
|
||||||
int state = 0;
|
int state = 0;
|
||||||
@@ -276,7 +277,7 @@ std::vector<audio::orchestra::DeviceInfo> audio::orchestra::api::pulse::getDevic
|
|||||||
// We can't do anything until PA is ready, so just iterate the mainloop
|
// We can't do anything until PA is ready, so just iterate the mainloop
|
||||||
// and continue
|
// and continue
|
||||||
if (pulseAudioReady == 0) {
|
if (pulseAudioReady == 0) {
|
||||||
pa_mainloop_iterate(pulseAudioMainLoop, 1, nullptr);
|
pa_mainloop_iterate(pulseAudioMainLoop, 1, null);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// We couldn't get a connection to the server, so exit out
|
// We couldn't get a connection to the server, so exit out
|
||||||
@@ -330,7 +331,7 @@ std::vector<audio::orchestra::DeviceInfo> audio::orchestra::api::pulse::getDevic
|
|||||||
}
|
}
|
||||||
// Iterate the main loop ..
|
// Iterate the main loop ..
|
||||||
if (playLoop == true) {
|
if (playLoop == true) {
|
||||||
pa_mainloop_iterate(pulseAudioMainLoop, 1, nullptr);
|
pa_mainloop_iterate(pulseAudioMainLoop, 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: need to do it better ...
|
// TODO: need to do it better ...
|
||||||
|
@@ -7,14 +7,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifdef ORCHESTRA_BUILD_PULSE
|
#ifdef ORCHESTRA_BUILD_PULSE
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.hpp>
|
||||||
#include <audio/orchestra/DeviceInfo.h>
|
#include <audio/orchestra/DeviceInfo.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
namespace api {
|
namespace api {
|
||||||
namespace pulse {
|
namespace pulse {
|
||||||
std::vector<audio::orchestra::DeviceInfo> getDeviceList();
|
etk::Vector<audio::orchestra::DeviceInfo> getDeviceList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,25 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
* @license APACHE v2.0 (see license file)
|
|
||||||
* @fork from RTAudio
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
|
||||||
#include <chrono>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <audio/channel.h>
|
|
||||||
#include <audio/format.h>
|
|
||||||
#include <audio/orchestra/error.h>
|
|
||||||
#include <audio/orchestra/status.h>
|
|
||||||
#include <audio/orchestra/Flags.h>
|
|
||||||
|
|
||||||
#include <audio/orchestra/CallbackInfo.h>
|
|
||||||
#include <audio/orchestra/DeviceInfo.h>
|
|
||||||
#include <audio/orchestra/StreamOptions.h>
|
|
||||||
#include <audio/orchestra/StreamParameters.h>
|
|
||||||
|
|
25
audio/orchestra/base.hpp
Normal file
25
audio/orchestra/base.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
* @fork from RTAudio
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ethread/Thread.hpp>
|
||||||
|
#include <ethread/Semaphore.hpp>
|
||||||
|
#include <ethread/Mutex.hpp>
|
||||||
|
#include <echrono/Steady.hpp>
|
||||||
|
#include <etk/Function.hpp>
|
||||||
|
#include <ememory/memory.hpp>
|
||||||
|
#include <audio/channel.hpp>
|
||||||
|
#include <audio/format.hpp>
|
||||||
|
#include <audio/orchestra/error.hpp>
|
||||||
|
#include <audio/orchestra/status.hpp>
|
||||||
|
#include <audio/orchestra/Flags.hpp>
|
||||||
|
|
||||||
|
#include <audio/orchestra/CallbackInfo.hpp>
|
||||||
|
#include <audio/orchestra/DeviceInfo.hpp>
|
||||||
|
#include <audio/orchestra/StreamOptions.hpp>
|
||||||
|
#include <audio/orchestra/StreamParameters.hpp>
|
||||||
|
|
@@ -5,7 +5,7 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
|
||||||
int32_t audio::orchestra::getLogId() {
|
int32_t audio::orchestra::getLogId() {
|
||||||
static int32_t g_val = elog::registerInstance("audio-orchestra");
|
static int32_t g_val = elog::registerInstance("audio-orchestra");
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <elog/log.h>
|
#include <elog/log.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
@@ -5,5 +5,5 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/error.h>
|
#include <audio/orchestra/error.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
@@ -5,8 +5,8 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/mode.h>
|
#include <audio/orchestra/mode.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
|
|
||||||
int32_t audio::orchestra::modeToIdTable(enum mode _mode) {
|
int32_t audio::orchestra::modeToIdTable(enum mode _mode) {
|
||||||
switch (_mode) {
|
switch (_mode) {
|
||||||
@@ -20,7 +20,7 @@ int32_t audio::orchestra::modeToIdTable(enum mode _mode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& audio::operator <<(std::ostream& _os, enum audio::orchestra::mode _obj) {
|
etk::Stream& audio::operator <<(etk::Stream& _os, enum audio::orchestra::mode _obj) {
|
||||||
switch (_obj) {
|
switch (_obj) {
|
||||||
case audio::orchestra::mode_unknow:
|
case audio::orchestra::mode_unknow:
|
||||||
_os << "unknow";
|
_os << "unknow";
|
||||||
|
@@ -6,7 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.hpp>
|
||||||
|
#include <etk/Stream.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
@@ -18,6 +19,6 @@ namespace audio {
|
|||||||
};
|
};
|
||||||
int32_t modeToIdTable(enum mode _mode);
|
int32_t modeToIdTable(enum mode _mode);
|
||||||
}
|
}
|
||||||
std::ostream& operator <<(std::ostream& _os, enum audio::orchestra::mode _obj);
|
etk::Stream& operator <<(etk::Stream& _os, enum audio::orchestra::mode _obj);
|
||||||
}
|
}
|
||||||
|
|
@@ -6,15 +6,15 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.hpp>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace orchestra {
|
namespace orchestra {
|
||||||
enum state {
|
enum class state {
|
||||||
state_closed,
|
closed,
|
||||||
state_stopped,
|
stopped,
|
||||||
state_stopping,
|
stopping,
|
||||||
state_running
|
running
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,28 +5,28 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/status.h>
|
#include <audio/orchestra/status.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
static const char* listValue[] = {
|
static const char* listValue[] = {
|
||||||
"ok",
|
"ok",
|
||||||
"overflow",
|
"overflow",
|
||||||
"underflow"
|
"underflow"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& audio::orchestra::operator <<(std::ostream& _os, enum audio::orchestra::status _obj) {
|
etk::Stream& audio::orchestra::operator <<(etk::Stream& _os, enum audio::orchestra::status _obj) {
|
||||||
_os << listValue[_obj];
|
_os << listValue[int32_t(_obj)];
|
||||||
return _os;
|
return _os;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& audio::orchestra::operator <<(std::ostream& _os, const std::vector<enum audio::orchestra::status>& _obj) {
|
etk::Stream& audio::orchestra::operator <<(etk::Stream& _os, const etk::Vector<enum audio::orchestra::status>& _obj) {
|
||||||
_os << std::string("{");
|
_os << etk::String("{");
|
||||||
for (size_t iii=0; iii<_obj.size(); ++iii) {
|
for (size_t iii=0; iii<_obj.size(); ++iii) {
|
||||||
if (iii!=0) {
|
if (iii!=0) {
|
||||||
_os << std::string(";");
|
_os << etk::String(";");
|
||||||
}
|
}
|
||||||
_os << _obj[iii];
|
_os << _obj[iii];
|
||||||
}
|
}
|
||||||
_os << std::string("}");
|
_os << etk::String("}");
|
||||||
return _os;
|
return _os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
* @license APACHE v2.0 (see license file)
|
|
||||||
* @fork from RTAudio
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
|
|
||||||
namespace audio {
|
|
||||||
namespace orchestra {
|
|
||||||
enum status {
|
|
||||||
status_ok, //!< nothing...
|
|
||||||
status_overflow, //!< Internal buffer has more data than they can accept
|
|
||||||
status_underflow //!< The internal buffer is empty
|
|
||||||
};
|
|
||||||
std::ostream& operator <<(std::ostream& _os, enum audio::orchestra::status _obj);
|
|
||||||
std::ostream& operator <<(std::ostream& _os, const std::vector<enum audio::orchestra::status>& _obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
23
audio/orchestra/status.hpp
Normal file
23
audio/orchestra/status.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
* @fork from RTAudio
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <etk/types.hpp>
|
||||||
|
#include <etk/Vector.hpp>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace orchestra {
|
||||||
|
enum class status {
|
||||||
|
ok, //!< nothing...
|
||||||
|
overflow, //!< Internal buffer has more data than they can accept
|
||||||
|
underflow //!< The internal buffer is empty
|
||||||
|
};
|
||||||
|
etk::Stream& operator <<(etk::Stream& _os, enum audio::orchestra::status _obj);
|
||||||
|
etk::Stream& operator <<(etk::Stream& _os, const etk::Vector<enum audio::orchestra::status>& _obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -5,24 +5,17 @@
|
|||||||
* @fork from RTAudio
|
* @fork from RTAudio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/orchestra/type.h>
|
#include <audio/orchestra/type.hpp>
|
||||||
#include <audio/orchestra/debug.h>
|
#include <audio/orchestra/debug.hpp>
|
||||||
#include <iostream>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#undef __class__
|
const etk::String audio::orchestra::typeUndefined = "undefined";
|
||||||
#define __class__ "type"
|
const etk::String audio::orchestra::typeAlsa = "alsa";
|
||||||
|
const etk::String audio::orchestra::typePulse = "pulse";
|
||||||
const std::string audio::orchestra::type_undefined = "undefined";
|
const etk::String audio::orchestra::typeOss = "oss";
|
||||||
const std::string audio::orchestra::type_alsa = "alsa";
|
const etk::String audio::orchestra::typeJack = "jack";
|
||||||
const std::string audio::orchestra::type_pulse = "pulse";
|
const etk::String audio::orchestra::typeCoreOSX = "coreOSX";
|
||||||
const std::string audio::orchestra::type_oss = "oss";
|
const etk::String audio::orchestra::typeCoreIOS = "coreIOS";
|
||||||
const std::string audio::orchestra::type_jack = "jack";
|
const etk::String audio::orchestra::typeAsio = "asio";
|
||||||
const std::string audio::orchestra::type_coreOSX = "coreOSX";
|
const etk::String audio::orchestra::typeDs = "ds";
|
||||||
const std::string audio::orchestra::type_coreIOS = "coreIOS";
|
const etk::String audio::orchestra::typeJava = "java";
|
||||||
const std::string audio::orchestra::type_asio = "asio";
|
const etk::String audio::orchestra::typeDummy = "dummy";
|
||||||
const std::string audio::orchestra::type_ds = "ds";
|
|
||||||
const std::string audio::orchestra::type_java = "java";
|
|
||||||
const std::string audio::orchestra::type_dummy = "dummy";
|
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
* @license APACHE v2.0 (see license file)
|
|
||||||
* @fork from RTAudio
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/stdTools.h>
|
|
||||||
|
|
||||||
namespace audio {
|
|
||||||
namespace orchestra {
|
|
||||||
/**
|
|
||||||
* @brief Audio API specifier arguments.
|
|
||||||
*/
|
|
||||||
extern const std::string type_undefined; //!< Error API.
|
|
||||||
extern const std::string type_alsa; //!< LINUX The Advanced Linux Sound Architecture.
|
|
||||||
extern const std::string type_pulse; //!< LINUX The Linux PulseAudio.
|
|
||||||
extern const std::string type_oss; //!< LINUX The Linux Open Sound System.
|
|
||||||
extern const std::string type_jack; //!< UNIX The Jack Low-Latency Audio Server.
|
|
||||||
extern const std::string type_coreOSX; //!< Macintosh OSX Core Audio.
|
|
||||||
extern const std::string type_coreIOS; //!< Macintosh iOS Core Audio.
|
|
||||||
extern const std::string type_asio; //!< WINDOWS The Steinberg Audio Stream I/O.
|
|
||||||
extern const std::string type_ds; //!< WINDOWS The Microsoft Direct Sound.
|
|
||||||
extern const std::string type_java; //!< ANDROID Interface.
|
|
||||||
extern const std::string type_dummy; //!< Empty wrapper (non-functional).
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
30
audio/orchestra/type.hpp
Normal file
30
audio/orchestra/type.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
* @fork from RTAudio
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <etk/types.hpp>
|
||||||
|
#include <etk/stdTools.hpp>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace orchestra {
|
||||||
|
/**
|
||||||
|
* @brief Audio API specifier arguments.
|
||||||
|
*/
|
||||||
|
extern const etk::String typeUndefined; //!< Error API.
|
||||||
|
extern const etk::String typeAlsa; //!< LINUX The Advanced Linux Sound Architecture.
|
||||||
|
extern const etk::String typePulse; //!< LINUX The Linux PulseAudio.
|
||||||
|
extern const etk::String typeOss; //!< LINUX The Linux Open Sound System.
|
||||||
|
extern const etk::String typeJack; //!< UNIX The Jack Low-Latency Audio Server.
|
||||||
|
extern const etk::String typeCoreOSX; //!< Macintosh OSX Core Audio.
|
||||||
|
extern const etk::String typeCoreIOS; //!< Macintosh iOS Core Audio.
|
||||||
|
extern const etk::String typeAsio; //!< WINDOWS The Steinberg Audio Stream I/O.
|
||||||
|
extern const etk::String typeDs; //!< WINDOWS The Microsoft Direct Sound.
|
||||||
|
extern const etk::String typeJava; //!< ANDROID Interface.
|
||||||
|
extern const etk::String typeDummy; //!< Empty wrapper (non-functional).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
authors.txt
Normal file
1
authors.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
MR Edouard DUPIN <yui.heero@gmail.com>
|
@@ -1,91 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.3)
|
|
||||||
project(audio_orchestra)
|
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
|
|
||||||
## Find catkin macros and libraries
|
|
||||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
|
||||||
## is used, also find other catkin packages
|
|
||||||
find_package(catkin REQUIRED COMPONENTS
|
|
||||||
etk
|
|
||||||
audio
|
|
||||||
)
|
|
||||||
|
|
||||||
find_package(ALSA REQUIRED)
|
|
||||||
|
|
||||||
###################################
|
|
||||||
## catkin specific configuration ##
|
|
||||||
###################################
|
|
||||||
## The catkin_package macro generates cmake config files for your package
|
|
||||||
## Declare things to be passed to dependent projects
|
|
||||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
|
||||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
|
||||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
|
||||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
|
||||||
catkin_package(
|
|
||||||
INCLUDE_DIRS ../
|
|
||||||
LIBRARIES ${PROJECT_NAME}
|
|
||||||
CATKIN_DEPENDS etk audio
|
|
||||||
DEPENDS system_lib
|
|
||||||
)
|
|
||||||
|
|
||||||
###########
|
|
||||||
## Build ##
|
|
||||||
###########
|
|
||||||
|
|
||||||
## Specify additional locations of header files
|
|
||||||
## Your package locations should be listed before other locations
|
|
||||||
include_directories(
|
|
||||||
..
|
|
||||||
${catkin_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
## Declare a cpp library
|
|
||||||
add_library(${PROJECT_NAME}
|
|
||||||
../audio/orchestra/debug.cpp
|
|
||||||
../audio/orchestra/status.cpp
|
|
||||||
../audio/orchestra/type.cpp
|
|
||||||
../audio/orchestra/mode.cpp
|
|
||||||
../audio/orchestra/state.cpp
|
|
||||||
../audio/orchestra/error.cpp
|
|
||||||
../audio/orchestra/base.cpp
|
|
||||||
../audio/orchestra/Interface.cpp
|
|
||||||
../audio/orchestra/Flags.cpp
|
|
||||||
../audio/orchestra/Api.cpp
|
|
||||||
../audio/orchestra/DeviceInfo.cpp
|
|
||||||
../audio/orchestra/StreamOptions.cpp
|
|
||||||
../audio/orchestra/api/Dummy.cpp
|
|
||||||
../audio/orchestra/api/Alsa.cpp
|
|
||||||
../audio/orchestra/api/Jack.cpp
|
|
||||||
../audio/orchestra/api/Pulse.cpp
|
|
||||||
../audio/orchestra/api/Oss.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_definitions(-D__LINUX_ALSA__)
|
|
||||||
add_definitions(-D__DUMMY__)
|
|
||||||
|
|
||||||
## Add cmake target dependencies of the executable/library
|
|
||||||
## as an example, message headers may need to be generated before nodes
|
|
||||||
#add_dependencies(${PROJECT_NAME} test_perfo_core_generate_messages_cpp)
|
|
||||||
|
|
||||||
## Specify libraries to link a library or executable target against
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
|
||||||
${ALSA_LIBRARIES}
|
|
||||||
${catkin_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
#############
|
|
||||||
## Install ##
|
|
||||||
#############
|
|
||||||
|
|
||||||
## Mark executables and/or libraries for installation
|
|
||||||
install(TARGETS ${PROJECT_NAME}
|
|
||||||
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
|
||||||
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
|
||||||
)
|
|
||||||
|
|
||||||
## Mark cpp header files for installation
|
|
||||||
install(DIRECTORY ../audio/orchestra/
|
|
||||||
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
|
||||||
FILES_MATCHING PATTERN "*.h"
|
|
||||||
)
|
|
@@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<package>
|
|
||||||
<name>audio_orchestra</name>
|
|
||||||
<version>0.3.0</version>
|
|
||||||
<description>Ewol RTAudio fork</description>
|
|
||||||
<maintainer email="yui.heero@gmail.com">Edouard DUPIN</maintainer>
|
|
||||||
<license>Apache-2.0</license>
|
|
||||||
<build_depend>etk</build_depend>
|
|
||||||
<build_depend>audio</build_depend>
|
|
||||||
<buildtool_depend>catkin</buildtool_depend>
|
|
||||||
<run_depend>etk</run_depend>
|
|
||||||
<run_depend>audio</run_depend>
|
|
||||||
</package>
|
|
63
command_generateAddJavaSectionInClass.py
Normal file
63
command_generateAddJavaSectionInClass.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
##
|
||||||
|
## Android specific section
|
||||||
|
##
|
||||||
|
##################################################################
|
||||||
|
def generateAddJavaSectionInClass(target, module, package_name):
|
||||||
|
module.add_pkg("GENERATE_SECTION__IMPORT", [
|
||||||
|
"import org.musicdsp.orchestra.OrchestraManager;"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__DECLARE", [
|
||||||
|
"private OrchestraManager m_audioManagerHandle;"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__CONSTRUCTOR", [
|
||||||
|
"// load audio maneger if it does not work, it is not critical ...",
|
||||||
|
"try {",
|
||||||
|
" m_audioManagerHandle = new OrchestraManager();",
|
||||||
|
"} catch (RuntimeException e) {",
|
||||||
|
" Log.e(\"" + package_name + "\", \"Can not load Audio interface (maybe not really needed) :\" + e);",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_CREATE", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onCreate();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_START", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onStart();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_RESTART", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onRestart();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_RESUME", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onResume();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_PAUSE", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onPause();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_STOP", [
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onStop();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
module.add_pkg("GENERATE_SECTION__ON_DESTROY", [
|
||||||
|
"// Destroy the AdView.",
|
||||||
|
"if (m_audioManagerHandle != null) {",
|
||||||
|
" m_audioManagerHandle.onDestroy();",
|
||||||
|
"}"
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
83
doc/build.md
Normal file
83
doc/build.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
Build lib & build sample {#audio_orchestra_build}
|
||||||
|
========================
|
||||||
|
|
||||||
|
@tableofcontents
|
||||||
|
|
||||||
|
Download: {#audio_orchestra_build_download}
|
||||||
|
=========
|
||||||
|
|
||||||
|
ege use some tools to manage source and build it:
|
||||||
|
|
||||||
|
need google repo: {#audio_orchestra_build_download_repo}
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
see: http://source.android.com/source/downloading.html#installing-repo
|
||||||
|
|
||||||
|
On all platform:
|
||||||
|
```{.sh}
|
||||||
|
mkdir ~/.bin
|
||||||
|
PATH=~/.bin:$PATH
|
||||||
|
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
|
||||||
|
chmod a+x ~/.bin/repo
|
||||||
|
```
|
||||||
|
|
||||||
|
On ubuntu
|
||||||
|
```{.sh}
|
||||||
|
sudo apt-get install repo
|
||||||
|
```
|
||||||
|
|
||||||
|
On archlinux
|
||||||
|
```{.sh}
|
||||||
|
sudo pacman -S repo
|
||||||
|
```
|
||||||
|
|
||||||
|
lutin (build-system): {#audio_orchestra_build_download_lutin}
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
```{.sh}
|
||||||
|
pip install lutin --user
|
||||||
|
# optionnal dependency of lutin (manage image changing size for application release)
|
||||||
|
pip install pillow --user
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
dependency: {#audio_orchestra_build_download_dependency}
|
||||||
|
-----------
|
||||||
|
|
||||||
|
```{.sh}
|
||||||
|
mkdir -p WORKING_DIRECTORY/framework
|
||||||
|
cd WORKING_DIRECTORY/framework
|
||||||
|
repo init -u git://github.com/atria-soft/manifest.git
|
||||||
|
repo sync -j8
|
||||||
|
cd ../..
|
||||||
|
```
|
||||||
|
|
||||||
|
sources: {#audio_orchestra_build_download_sources}
|
||||||
|
--------
|
||||||
|
|
||||||
|
They are already download in the repo manifest in:
|
||||||
|
|
||||||
|
```{.sh}
|
||||||
|
cd WORKING_DIRECTORY/framework/atria-soft/audio_orchestra
|
||||||
|
```
|
||||||
|
|
||||||
|
Build: {#audio_orchestra_build_build}
|
||||||
|
======
|
||||||
|
|
||||||
|
you must stay in zour working directory...
|
||||||
|
```{.sh}
|
||||||
|
cd WORKING_DIRECTORY
|
||||||
|
```
|
||||||
|
|
||||||
|
library: {#audio_orchestra_build_build_library}
|
||||||
|
--------
|
||||||
|
|
||||||
|
```{.sh}
|
||||||
|
lutin -mdebug audio-orchestra
|
||||||
|
```
|
||||||
|
|
||||||
|
Sample: {#audio_orchestra_build_build_sample}
|
||||||
|
-------
|
||||||
|
|
||||||
|
No smaple availlable for now ...
|
||||||
|
|
50
doc/mainpage.md
Normal file
50
doc/mainpage.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
AUDIO-ORCHESTRA library {#mainpage}
|
||||||
|
=======================
|
||||||
|
|
||||||
|
@tableofcontents
|
||||||
|
|
||||||
|
What is AUDIO-ORCHESTRA: {#audio_orchestra_mainpage_what}
|
||||||
|
========================
|
||||||
|
|
||||||
|
AUDIO-ORCHESTRA, is a fork of RTAudio lib (with port for Android, and IOs).
|
||||||
|
|
||||||
|
This is a cross API of Audio wrapping the Hardware.
|
||||||
|
|
||||||
|
This library is not friendy usable, use audio-river to have a correct and simple multiple-flow API
|
||||||
|
|
||||||
|
What it does: {#audio_orchestra_mainpage_what_it_does}
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Open a strem audio in Input or output
|
||||||
|
- synchronise 2 flow
|
||||||
|
- open on some platform: Android, Linux, MacOs, Ios, Windows
|
||||||
|
|
||||||
|
AUDIO-ORCHESTRA is dependent of the STL (compatible with MacOs stl (CXX))
|
||||||
|
|
||||||
|
|
||||||
|
What languages are supported? {#audio_orchestra_mainpage_language}
|
||||||
|
=============================
|
||||||
|
|
||||||
|
AUDIO-ORCHESTRA is written in C++.
|
||||||
|
|
||||||
|
|
||||||
|
Are there any licensing restrictions? {#audio_orchestra_mainpage_license_restriction}
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
AUDIO-ORCHESTRA is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
|
||||||
|
|
||||||
|
|
||||||
|
License (MIT) {#audio_orchestra_mainpage_license}
|
||||||
|
=============
|
||||||
|
|
||||||
|
Copyright AUDIO-ORCHESTRA Edouard DUPIN
|
||||||
|
|
||||||
|
MIT ...
|
||||||
|
|
||||||
|
|
||||||
|
Other pages {#audio_orchestra_mainpage_sub_page}
|
||||||
|
===========
|
||||||
|
|
||||||
|
- @ref audio_orchestra_build
|
||||||
|
- [**ewol coding style**](http://atria-soft.github.io/ewol/ewol_coding_style.html)
|
||||||
|
|
32
doxy_audio-orchestra.py
Normal file
32
doxy_audio-orchestra.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import os
|
||||||
|
import doxy.module as module
|
||||||
|
import doxy.debug as debug
|
||||||
|
import doxy.tools as tools
|
||||||
|
|
||||||
|
def create(target, module_name):
|
||||||
|
my_module = module.Module(__file__, module_name)
|
||||||
|
my_module.set_version("version.txt")
|
||||||
|
my_module.set_title("Orchestra: audio interface wrapper")
|
||||||
|
my_module.set_website("http://musicdsp.github.io/" + module_name)
|
||||||
|
my_module.set_website_sources("http://github.com/musicdsp/" + module_name)
|
||||||
|
my_module.add_path([
|
||||||
|
"audio",
|
||||||
|
"doc"
|
||||||
|
])
|
||||||
|
my_module.add_depend([
|
||||||
|
'etk',
|
||||||
|
'audio',
|
||||||
|
])
|
||||||
|
my_module.add_exclude_symbols([
|
||||||
|
'*operator<<*',
|
||||||
|
])
|
||||||
|
my_module.add_exclude_file([
|
||||||
|
'debug.h',
|
||||||
|
])
|
||||||
|
my_module.add_file_patterns([
|
||||||
|
'*.h',
|
||||||
|
'*.md',
|
||||||
|
])
|
||||||
|
|
||||||
|
return my_module
|
@@ -1,181 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
import lutin.module as module
|
|
||||||
import lutin.tools as tools
|
|
||||||
import lutin.debug as debug
|
|
||||||
|
|
||||||
|
|
||||||
def get_type():
|
|
||||||
return "LIBRARY"
|
|
||||||
|
|
||||||
def get_desc():
|
|
||||||
return "Generic wrapper on all audio interface"
|
|
||||||
|
|
||||||
def get_licence():
|
|
||||||
return "APACHE-2"
|
|
||||||
|
|
||||||
def get_compagny_type():
|
|
||||||
return "com"
|
|
||||||
|
|
||||||
def get_compagny_name():
|
|
||||||
return "atria-soft"
|
|
||||||
|
|
||||||
def get_maintainer():
|
|
||||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
|
||||||
|
|
||||||
def get_version():
|
|
||||||
return [0,0,0]
|
|
||||||
|
|
||||||
def create(target, module_name):
|
|
||||||
my_module = module.Module(__file__, module_name, get_type())
|
|
||||||
my_module.add_src_file([
|
|
||||||
'audio/orchestra/debug.cpp',
|
|
||||||
'audio/orchestra/status.cpp',
|
|
||||||
'audio/orchestra/type.cpp',
|
|
||||||
'audio/orchestra/mode.cpp',
|
|
||||||
'audio/orchestra/state.cpp',
|
|
||||||
'audio/orchestra/error.cpp',
|
|
||||||
'audio/orchestra/base.cpp',
|
|
||||||
'audio/orchestra/Interface.cpp',
|
|
||||||
'audio/orchestra/Flags.cpp',
|
|
||||||
'audio/orchestra/Api.cpp',
|
|
||||||
'audio/orchestra/DeviceInfo.cpp',
|
|
||||||
'audio/orchestra/StreamOptions.cpp',
|
|
||||||
'audio/orchestra/api/Dummy.cpp'
|
|
||||||
])
|
|
||||||
my_module.add_header_file([
|
|
||||||
'audio/orchestra/debug.h',
|
|
||||||
'audio/orchestra/status.h',
|
|
||||||
'audio/orchestra/type.h',
|
|
||||||
'audio/orchestra/mode.h',
|
|
||||||
'audio/orchestra/state.h',
|
|
||||||
'audio/orchestra/error.h',
|
|
||||||
'audio/orchestra/base.h',
|
|
||||||
'audio/orchestra/Interface.h',
|
|
||||||
'audio/orchestra/Flags.h',
|
|
||||||
'audio/orchestra/Api.h',
|
|
||||||
'audio/orchestra/DeviceInfo.h',
|
|
||||||
'audio/orchestra/StreamOptions.h',
|
|
||||||
'audio/orchestra/CallbackInfo.h',
|
|
||||||
'audio/orchestra/StreamParameters.h'
|
|
||||||
])
|
|
||||||
my_module.add_module_depend(['audio', 'etk'])
|
|
||||||
# add all the time the dummy interface
|
|
||||||
my_module.add_export_flag('c++', ['-DORCHESTRA_BUILD_DUMMY'])
|
|
||||||
# TODO : Add a FILE interface:
|
|
||||||
|
|
||||||
if target.name=="Windows":
|
|
||||||
my_module.add_src_file([
|
|
||||||
'audio/orchestra/api/Asio.cpp',
|
|
||||||
'audio/orchestra/api/Ds.cpp',
|
|
||||||
])
|
|
||||||
# load optionnal API:
|
|
||||||
my_module.add_optionnal_module_depend('asio', ["c++", "-DORCHESTRA_BUILD_ASIO"])
|
|
||||||
my_module.add_optionnal_module_depend('ds', ["c++", "-DORCHESTRA_BUILD_DS"])
|
|
||||||
my_module.add_optionnal_module_depend('wasapi', ["c++", "-DORCHESTRA_BUILD_WASAPI"])
|
|
||||||
elif target.name=="Linux":
|
|
||||||
my_module.add_src_file([
|
|
||||||
'audio/orchestra/api/Alsa.cpp',
|
|
||||||
'audio/orchestra/api/Jack.cpp',
|
|
||||||
'audio/orchestra/api/Pulse.cpp',
|
|
||||||
'audio/orchestra/api/PulseDeviceList.cpp'
|
|
||||||
])
|
|
||||||
my_module.add_optionnal_module_depend('alsa', ["c++", "-DORCHESTRA_BUILD_ALSA"])
|
|
||||||
my_module.add_optionnal_module_depend('jack', ["c++", "-DORCHESTRA_BUILD_JACK"])
|
|
||||||
my_module.add_optionnal_module_depend('pulse', ["c++", "-DORCHESTRA_BUILD_PULSE"])
|
|
||||||
elif target.name=="MacOs":
|
|
||||||
my_module.add_src_file([
|
|
||||||
'audio/orchestra/api/Core.cpp'
|
|
||||||
])
|
|
||||||
# MacOsX core
|
|
||||||
my_module.add_optionnal_module_depend('CoreAudio', ["c++", "-DORCHESTRA_BUILD_MACOSX_CORE"])
|
|
||||||
elif target.name=="IOs":
|
|
||||||
my_module.add_src_file('audio/orchestra/api/CoreIos.mm')
|
|
||||||
# IOsX core
|
|
||||||
my_module.add_optionnal_module_depend('CoreAudio', ["c++", "-DORCHESTRA_BUILD_IOS_CORE"])
|
|
||||||
elif target.name=="Android":
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraConstants.java')
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraManagerCallback.java')
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraNative.java')
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraInterfaceInput.java')
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraInterfaceOutput.java')
|
|
||||||
my_module.add_src_file('android/org/musicdsp/orchestra/OrchestraManager.java')
|
|
||||||
# create inter language interface
|
|
||||||
my_module.add_src_file('org.musicdsp.orchestra.OrchestraConstants.javah')
|
|
||||||
my_module.add_path(tools.get_current_path(__file__) + '/android/', type='java')
|
|
||||||
my_module.add_module_depend(['SDK', 'jvm-basics', 'ejson'])
|
|
||||||
my_module.add_export_flag('c++', ['-DORCHESTRA_BUILD_JAVA'])
|
|
||||||
|
|
||||||
my_module.add_src_file('audio/orchestra/api/Android.cpp')
|
|
||||||
my_module.add_src_file('audio/orchestra/api/AndroidNativeInterface.cpp')
|
|
||||||
# add tre creator of the basic java class ...
|
|
||||||
target.add_action("BINARY", 11, "audio-orchestra-out-wrapper", tool_generate_add_java_section_in_class)
|
|
||||||
else:
|
|
||||||
debug.warning("unknow target for audio_orchestra : " + target.name);
|
|
||||||
|
|
||||||
my_module.add_path(tools.get_current_path(__file__))
|
|
||||||
|
|
||||||
return my_module
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##################################################################
|
|
||||||
##
|
|
||||||
## Android specific section
|
|
||||||
##
|
|
||||||
##################################################################
|
|
||||||
def tool_generate_add_java_section_in_class(target, module, package_name):
|
|
||||||
module.pkg_add("GENERATE_SECTION__IMPORT", [
|
|
||||||
"import org.musicdsp.orchestra.OrchestraManager;"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__DECLARE", [
|
|
||||||
"private OrchestraManager m_audioManagerHandle;"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__CONSTRUCTOR", [
|
|
||||||
"// load audio maneger if it does not work, it is not critical ...",
|
|
||||||
"try {",
|
|
||||||
" m_audioManagerHandle = new OrchestraManager();",
|
|
||||||
"} catch (RuntimeException e) {",
|
|
||||||
" Log.e(\"" + package_name + "\", \"Can not load Audio interface (maybe not really needed) :\" + e);",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_CREATE", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onCreate();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_START", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onStart();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_RESTART", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onRestart();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_RESUME", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onResume();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_PAUSE", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onPause();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_STOP", [
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onStop();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
module.pkg_add("GENERATE_SECTION__ON_DESTROY", [
|
|
||||||
"// Destroy the AdView.",
|
|
||||||
"if (m_audioManagerHandle != null) {",
|
|
||||||
" m_audioManagerHandle.onDestroy();",
|
|
||||||
"}"
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
20
tools/GLD_orchestra-in.json
Normal file
20
tools/GLD_orchestra-in.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "BINARY",
|
||||||
|
"sub-type": "TOOL",
|
||||||
|
"group-id": "com.atria-soft",
|
||||||
|
"description": "'in' tool for orchestra",
|
||||||
|
"license": "MPL-2",
|
||||||
|
"license-file": "file://../LICENSE",
|
||||||
|
"maintainer": "file://../authors.txt",
|
||||||
|
"author": "file://../authors.txt",
|
||||||
|
"version": "file://../version.txt",
|
||||||
|
"code-quality": "MEDIUM",
|
||||||
|
|
||||||
|
"source": [
|
||||||
|
"orchestra-in.cpp"
|
||||||
|
],
|
||||||
|
"dependency": [
|
||||||
|
"audio-orchestra",
|
||||||
|
"test-debug"
|
||||||
|
]
|
||||||
|
}
|
20
tools/GLD_orchestra-list.json
Normal file
20
tools/GLD_orchestra-list.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "BINARY",
|
||||||
|
"sub-type": "TOOL",
|
||||||
|
"group-id": "com.atria-soft",
|
||||||
|
"description": "'list' i/o tool for orchestra",
|
||||||
|
"license": "MPL-2",
|
||||||
|
"license-file": "file://../LICENSE",
|
||||||
|
"maintainer": "file://../authors.txt",
|
||||||
|
"author": "file://../authors.txt",
|
||||||
|
"version": "file://../version.txt",
|
||||||
|
"code-quality": "MEDIUM",
|
||||||
|
|
||||||
|
"source": [
|
||||||
|
"orchestra-list.cpp"
|
||||||
|
],
|
||||||
|
"dependency": [
|
||||||
|
"audio-orchestra",
|
||||||
|
"test-debug"
|
||||||
|
]
|
||||||
|
}
|
20
tools/GLD_orchestra-out.json
Normal file
20
tools/GLD_orchestra-out.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "BINARY",
|
||||||
|
"sub-type": "TOOL",
|
||||||
|
"group-id": "com.atria-soft",
|
||||||
|
"description": "'out' i/o tool for orchestra",
|
||||||
|
"license": "MPL-2",
|
||||||
|
"license-file": "file://../LICENSE",
|
||||||
|
"maintainer": "file://../authors.txt",
|
||||||
|
"author": "file://../authors.txt",
|
||||||
|
"version": "file://../version.txt",
|
||||||
|
"code-quality": "MEDIUM",
|
||||||
|
|
||||||
|
"source": [
|
||||||
|
"orchestra-out.cpp"
|
||||||
|
],
|
||||||
|
"dependency": [
|
||||||
|
"audio-orchestra",
|
||||||
|
"test-debug"
|
||||||
|
]
|
||||||
|
}
|
@@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
import lutin.module as module
|
|
||||||
import lutin.tools as tools
|
|
||||||
import lutin.debug as debug
|
|
||||||
|
|
||||||
|
|
||||||
def get_type():
|
|
||||||
return "BINARY"
|
|
||||||
|
|
||||||
def get_sub_type():
|
|
||||||
return "TOOLS"
|
|
||||||
|
|
||||||
def get_desc():
|
|
||||||
return "'in' tool for orchestra"
|
|
||||||
|
|
||||||
def get_licence():
|
|
||||||
return "APACHE-2"
|
|
||||||
|
|
||||||
def get_compagny_type():
|
|
||||||
return "com"
|
|
||||||
|
|
||||||
def get_compagny_name():
|
|
||||||
return "atria-soft"
|
|
||||||
|
|
||||||
def get_maintainer():
|
|
||||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
|
||||||
|
|
||||||
def create(target, module_name):
|
|
||||||
my_module = module.Module(__file__, module_name, get_type())
|
|
||||||
|
|
||||||
my_module.add_src_file([
|
|
||||||
'orchestra-in.cpp'
|
|
||||||
])
|
|
||||||
my_module.add_module_depend(['audio-orchestra', 'test-debug'])
|
|
||||||
return my_module
|
|
||||||
|
|
||||||
|
|
@@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
import lutin.module as module
|
|
||||||
import lutin.tools as tools
|
|
||||||
import lutin.debug as debug
|
|
||||||
|
|
||||||
|
|
||||||
def get_type():
|
|
||||||
return "BINARY"
|
|
||||||
|
|
||||||
def get_sub_type():
|
|
||||||
return "TOOLS"
|
|
||||||
|
|
||||||
def get_desc():
|
|
||||||
return "'list' i/o tool for orchestra"
|
|
||||||
|
|
||||||
def get_licence():
|
|
||||||
return "APACHE-2"
|
|
||||||
|
|
||||||
def get_compagny_type():
|
|
||||||
return "com"
|
|
||||||
|
|
||||||
def get_compagny_name():
|
|
||||||
return "atria-soft"
|
|
||||||
|
|
||||||
def get_maintainer():
|
|
||||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
|
||||||
|
|
||||||
def create(target, module_name):
|
|
||||||
my_module = module.Module(__file__, module_name, get_type())
|
|
||||||
|
|
||||||
my_module.add_src_file([
|
|
||||||
'orchestra-list.cpp'
|
|
||||||
])
|
|
||||||
my_module.add_module_depend(['audio-orchestra', 'test-debug'])
|
|
||||||
return my_module
|
|
||||||
|
|
||||||
|
|
@@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
import lutin.module as module
|
|
||||||
import lutin.tools as tools
|
|
||||||
import lutin.debug as debug
|
|
||||||
|
|
||||||
|
|
||||||
def get_type():
|
|
||||||
return "BINARY"
|
|
||||||
|
|
||||||
def get_sub_type():
|
|
||||||
return "TOOLS"
|
|
||||||
|
|
||||||
def get_desc():
|
|
||||||
return "'out' tool for orchestra"
|
|
||||||
|
|
||||||
def get_licence():
|
|
||||||
return "APACHE-2"
|
|
||||||
|
|
||||||
def get_compagny_type():
|
|
||||||
return "com"
|
|
||||||
|
|
||||||
def get_compagny_name():
|
|
||||||
return "atria-soft"
|
|
||||||
|
|
||||||
def get_maintainer():
|
|
||||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
|
||||||
|
|
||||||
def create(target, module_name):
|
|
||||||
my_module = module.Module(__file__, module_name, get_type())
|
|
||||||
|
|
||||||
my_module.add_src_file([
|
|
||||||
'orchestra-out.cpp'
|
|
||||||
])
|
|
||||||
my_module.add_module_depend(['audio-orchestra', 'test-debug'])
|
|
||||||
return my_module
|
|
||||||
|
|
||||||
|
|
@@ -4,20 +4,20 @@
|
|||||||
* @license APACHE v2.0 (see license file)
|
* @license APACHE v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <etk/etk.h>
|
#include <etk/etk.hpp>
|
||||||
#include <test-debug/debug.h>
|
#include <test-debug/debug.hpp>
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
|
|
||||||
int main(int _argc, const char **_argv) {
|
int main(int _argc, const char **_argv) {
|
||||||
// the only one init for etk:
|
// the only one init for etk:
|
||||||
etk::init(_argc, _argv);
|
etk::init(_argc, _argv);
|
||||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||||
std::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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,25 +4,25 @@
|
|||||||
* @license APACHE v2.0 (see license file)
|
* @license APACHE v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <etk/etk.h>
|
#include <etk/etk.hpp>
|
||||||
#include <test-debug/debug.h>
|
#include <test-debug/debug.hpp>
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
|
|
||||||
int main(int _argc, const char **_argv) {
|
int main(int _argc, const char **_argv) {
|
||||||
// the only one init for etk:
|
// the only one init for etk:
|
||||||
etk::init(_argc, _argv);
|
etk::init(_argc, _argv);
|
||||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||||
std::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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio::orchestra::Interface interface;
|
audio::orchestra::Interface interface;
|
||||||
std::vector<std::string> apis = interface.getListApi();
|
etk::Vector<etk::String> apis = interface.getListApi();
|
||||||
TEST_PRINT("Find : " << apis.size() << " apis.");
|
TEST_PRINT("Find : " << apis.size() << " apis.");
|
||||||
for (auto &it : apis) {
|
for (auto &it : apis) {
|
||||||
interface.instanciate(it);
|
interface.instanciate(it);
|
||||||
|
@@ -4,20 +4,20 @@
|
|||||||
* @license APACHE v2.0 (see license file)
|
* @license APACHE v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <etk/etk.h>
|
#include <etk/etk.hpp>
|
||||||
#include <test-debug/debug.h>
|
#include <test-debug/debug.hpp>
|
||||||
#include <unistd.h>
|
|
||||||
#include <audio/orchestra/Interface.h>
|
#include <audio/orchestra/Interface.hpp>
|
||||||
|
|
||||||
int main(int _argc, const char **_argv) {
|
int main(int _argc, const char **_argv) {
|
||||||
// the only one init for etk:
|
// the only one init for etk:
|
||||||
etk::init(_argc, _argv);
|
etk::init(_argc, _argv);
|
||||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||||
std::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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
version.txt
Normal file
1
version.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1.0.0-dev
|
Reference in New Issue
Block a user