[DEV] continue dev of android audio interface

This commit is contained in:
2015-06-22 21:39:29 +02:00
parent 07684a0e54
commit 7d0a38e087
8 changed files with 520 additions and 63 deletions

View File

@@ -11,60 +11,20 @@
#include <unistd.h>
#include <audio/orchestra/Interface.h>
#include <audio/orchestra/debug.h>
#include <audio/orchestra/api/AndroidNativeInterface.h>
#include <limits.h>
#undef __class__
#define __class__ "api::Android"
int32_t ttttttt();
audio::orchestra::Api* audio::orchestra::api::Android::create() {
ATA_INFO("Create Android device ... : " << ttttttt());
ATA_INFO("Create Android device ... ");
return new audio::orchestra::api::Android();
}
audio::orchestra::api::Android::Android() {
ATA_INFO("new Android");
// On android, we set a static device ...
ATA_INFO("get context");
#if 0
ewol::Context& tmpContext = ewol::getContext();
ATA_INFO("done p=" << (int64_t)&tmpContext);
int32_t deviceCount = tmpContext.audioGetDeviceCount();
ATA_ERROR("Get count devices : " << deviceCount);
for (int32_t iii=0; iii<deviceCount; ++iii) {
std::string property = tmpContext.audioGetDeviceProperty(iii);
ATA_ERROR("Get devices property : " << property);
std::vector<std::string> listProperty = etk::split(property, ':');
audio::orchestra::DeviceInfo tmp;
tmp.name = listProperty[0];
std::vector<std::string> listFreq = etk::split(listProperty[2], ',');
for(size_t fff=0; fff<listFreq.size(); ++fff) {
tmp.sampleRates.push_back(etk::string_to_int32_t(listFreq[fff]));
}
tmp.outputChannels = 0;
tmp.inputChannels = 0;
tmp.duplexChannels = 0;
if (listProperty[1] == "out") {
tmp.isDefaultOutput = true;
tmp.isDefaultInput = false;
tmp.outputChannels = etk::string_to_int32_t(listProperty[3]);
} else if (listProperty[1] == "in") {
tmp.isDefaultOutput = false;
tmp.isDefaultInput = true;
tmp.inputChannels = etk::string_to_int32_t(listProperty[3]);
} else {
/* duplex */
tmp.isDefaultOutput = true;
tmp.isDefaultInput = true;
tmp.duplexChannels = etk::string_to_int32_t(listProperty[3]);
}
tmp.nativeFormats = audio::getListFormatFromString(listProperty[4]);
m_devices.push_back(tmp);
}
#endif
ATA_INFO("Create Android interface (end)");
ATA_INFO("Create Android interface");
}
audio::orchestra::api::Android::~Android() {
@@ -73,16 +33,16 @@ audio::orchestra::api::Android::~Android() {
uint32_t audio::orchestra::api::Android::getDeviceCount() {
//ATA_INFO("Get device count:"<< m_devices.size());
return m_devices.size();
return audio::orchestra::api::android::getDeviceCount();
}
audio::orchestra::DeviceInfo audio::orchestra::api::Android::getDeviceInfo(uint32_t _device) {
//ATA_INFO("Get device info ...");
return m_devices[_device];
return audio::orchestra::api::android::getDeviceInfo(_device);
}
enum audio::orchestra::error audio::orchestra::api::Android::closeStream() {
ATA_INFO("Clese Stream");
ATA_INFO("Close Stream");
// Can not close the stream now...
return audio::orchestra::error_none;
}
@@ -168,6 +128,7 @@ bool audio::orchestra::api::Android::probeDeviceOpen(uint32_t _device,
const audio::orchestra::StreamOptions& _options) {
bool ret = false;
ATA_INFO("Probe : device=" << _device << " channels=" << _channels << " firstChannel=" << _firstChannel << " sampleRate=" << _sampleRate);
ret = audio::orchestra::api::android::open(_device, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options);
#if 0
if (_mode != audio::orchestra::mode_output) {
ATA_ERROR("Can not start a device input or duplex for Android ...");

View File

@@ -8,27 +8,357 @@
#include <pthread.h>
#include <mutex>
#include <audio/orchestra/debug.h>
#include <audio/orchestra/error.h>
#include <audio/orchestra/api/AndroidNativeInterface.h>
/* include auto generated file */
#include <org_musicdsp_orchestra_Constants.h>
#include <jvm-basics/jvm-basics.h>
#include <etk/memory.h>
#include <etk/tool.h>
#include <ejson/ejson.h>
class AndroidOrchestraContext {
public:
AndroidOrchestraContext(JNIEnv* _env,
jclass _classBase,
jobject _objCallback) {
ATA_ERROR("kjlkjlk");
// get a resources from the java environement :
JNIEnv* m_JavaVirtualMachinePointer; //!< the JVM
jclass m_javaClassOrchestra; //!< main activity class (android ...)
jclass m_javaClassOrchestraCallback;
jobject m_javaObjectOrchestraCallback;
jmethodID m_javaMethodOrchestraActivityAudioGetDeviceCount;
jmethodID m_javaMethodOrchestraActivityAudioGetDeviceProperty;
jmethodID m_javaMethodOrchestraActivityAudioOpenDevice;
jmethodID m_javaMethodOrchestraActivityAudioCloseDevice;
jclass m_javaDefaultClassString; //!< default string class
private:
bool safeInitMethodID(jmethodID& _mid, jclass& _cls, const char* _name, const char* _sign) {
_mid = m_JavaVirtualMachinePointer->GetMethodID(_cls, _name, _sign);
if(_mid == nullptr) {
ATA_ERROR("C->java : Can't find the method " << _name);
/* remove access on the virtual machine : */
m_JavaVirtualMachinePointer = nullptr;
return false;
}
return true;
}
bool java_attach_current_thread(int *_rstatus) {
ATA_DEBUG("C->java : call java");
if (jvm_basics::getJavaVM() == nullptr) {
ATA_ERROR("C->java : JVM not initialised");
m_JavaVirtualMachinePointer = nullptr;
return false;
}
*_rstatus = jvm_basics::getJavaVM()->GetEnv((void **) &m_JavaVirtualMachinePointer, JNI_VERSION_1_6);
if (*_rstatus == JNI_EDETACHED) {
JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "EwolNativeThread";
lJavaVMAttachArgs.group = nullptr;
int status = jvm_basics::getJavaVM()->AttachCurrentThread(&m_JavaVirtualMachinePointer, &lJavaVMAttachArgs);
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
if (status != JNI_OK) {
ATA_ERROR("C->java : AttachCurrentThread failed : " << status);
m_JavaVirtualMachinePointer = nullptr;
return false;
}
}
return true;
}
void java_detach_current_thread(int _status) {
if(_status == JNI_EDETACHED) {
jvm_basics::getJavaVM()->DetachCurrentThread();
m_JavaVirtualMachinePointer = nullptr;
}
}
public:
AndroidOrchestraContext(JNIEnv* _env, jclass _classBase, jobject _objCallback) :
m_JavaVirtualMachinePointer(nullptr),
m_javaClassOrchestra(0),
m_javaClassOrchestraCallback(0),
m_javaObjectOrchestraCallback(0),
m_javaMethodOrchestraActivityAudioGetDeviceCount(0),
m_javaMethodOrchestraActivityAudioGetDeviceProperty(0),
m_javaMethodOrchestraActivityAudioOpenDevice(0),
m_javaMethodOrchestraActivityAudioCloseDevice(0),
m_javaDefaultClassString(0) {
ATA_DEBUG("*******************************************");
ATA_DEBUG("** set JVM Pointer (orchestra) **");
ATA_DEBUG("*******************************************");
m_JavaVirtualMachinePointer = _env;
// get default needed all time elements :
if (m_JavaVirtualMachinePointer == nullptr) {
ATA_ERROR("C->java: NULLPTR jvm interface");
return;
}
ATA_DEBUG("C->java: try load org/musicdsp/orchestra/Orchestra class");
m_javaClassOrchestra = m_JavaVirtualMachinePointer->FindClass("org/musicdsp/orchestra/Orchestra" );
if (m_javaClassOrchestra == 0) {
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/Orchestra class");
// remove access on the virtual machine :
m_JavaVirtualMachinePointer = nullptr;
return;
}
/* The object field extends Activity and implement OrchestraCallback */
m_javaClassOrchestraCallback = m_JavaVirtualMachinePointer->GetObjectClass(_objCallback);
if(m_javaClassOrchestraCallback == nullptr) {
ATA_ERROR("C->java : Can't find org/musicdsp/orchestra/ManagerCallback class");
// remove access on the virtual machine :
m_JavaVirtualMachinePointer = nullptr;
return;
}
bool functionCallbackIsMissing = false;
bool ret= false;
ret = safeInitMethodID(m_javaMethodOrchestraActivityAudioGetDeviceCount,
m_javaClassOrchestraCallback,
"getDeviceCount",
"()I");
if (ret == false) {
jvm_basics::checkExceptionJavaVM(_env);
ATA_ERROR("system can not start without function : getDeviceCount");
functionCallbackIsMissing = true;
}
ret = safeInitMethodID(m_javaMethodOrchestraActivityAudioGetDeviceProperty,
m_javaClassOrchestraCallback,
"getDeviceProperty",
"(I)Ljava/lang/String;");
if (ret == false) {
jvm_basics::checkExceptionJavaVM(_env);
ATA_ERROR("system can not start without function : getDeviceProperty");
functionCallbackIsMissing = true;
}
ret = safeInitMethodID(m_javaMethodOrchestraActivityAudioOpenDevice,
m_javaClassOrchestraCallback,
"openDevice",
"(IIII)Z");
if (ret == false) {
jvm_basics::checkExceptionJavaVM(_env);
ATA_ERROR("system can not start without function : openDevice");
functionCallbackIsMissing = true;
}
ret = safeInitMethodID(m_javaMethodOrchestraActivityAudioCloseDevice,
m_javaClassOrchestraCallback,
"closeDevice",
"(I)Z");
if (ret == false) {
jvm_basics::checkExceptionJavaVM(_env);
ATA_ERROR("system can not start without function : closeDevice");
functionCallbackIsMissing = true;
}
m_javaObjectOrchestraCallback = _env->NewGlobalRef(_objCallback);
if (m_javaObjectOrchestraCallback == nullptr) {
functionCallbackIsMissing = true;
}
m_javaDefaultClassString = m_JavaVirtualMachinePointer->FindClass("java/lang/String" );
if (m_javaDefaultClassString == 0) {
ATA_ERROR("C->java : Can't find java/lang/String" );
// remove access on the virtual machine :
m_JavaVirtualMachinePointer = nullptr;
functionCallbackIsMissing = true;
}
if (functionCallbackIsMissing == true) {
ATA_CRITICAL(" mission one function ==> system can not work withut it...");
}
}
~AndroidOrchestraContext() {
// TODO ...
}
void unInit(JNIEnv* _env) {
_env->DeleteGlobalRef(m_javaObjectOrchestraCallback);
m_javaObjectOrchestraCallback = nullptr;
}
uint32_t getDeviceCount() {
// Request the clipBoard :
ATA_DEBUG("C->java : audio get device count");
int status;
if(!java_attach_current_thread(&status)) {
return 0;
}
ATA_DEBUG("Call CallIntMethod ...");
//Call java ...
jint ret = m_JavaVirtualMachinePointer->CallIntMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioGetDeviceCount);
// manage execption :
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
java_detach_current_thread(status);
return (uint32_t)ret;
return 0;
}
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _idDevice) {
audio::orchestra::DeviceInfo info;
// Request the clipBoard :
ATA_DEBUG("C->java : audio get device count");
int status;
if(!java_attach_current_thread(&status)) {
return info;
}
//Call java ...
jstring returnString = (jstring) m_JavaVirtualMachinePointer->CallObjectMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioGetDeviceProperty, _idDevice);
const char *js = m_JavaVirtualMachinePointer->GetStringUTFChars(returnString, nullptr);
std::string retString(js);
m_JavaVirtualMachinePointer->ReleaseStringUTFChars(returnString, js);
//m_JavaVirtualMachinePointer->DeleteLocalRef(returnString);
// manage execption :
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
java_detach_current_thread(status);
ATA_WARNING("get device information : " << retString);
ejson::Document doc;
if (doc.parse(retString) == false) {
return info;
}
info.name = doc.getStringValue("name", "no-name");
if (doc.getStringValue("type", "output") == "output") {
info.input = false;
} else {
info.input = true;
}
std11::shared_ptr<const ejson::Array> list = doc.getArray("sample-rate");
if (list != nullptr) {
for (size_t iii=0; iii<list->size(); ++iii) {
info.sampleRates.push_back(int32_t(list->getNumberValue(iii, 48000)));
}
}
list = doc.getArray("channels");
if (list != nullptr) {
for (size_t iii=0; iii<list->size(); ++iii) {
info.channels.push_back(audio::getChannelFromString(list->getStringValue(iii, "???")));
}
}
list = doc.getArray("format");
if (list != nullptr) {
for (size_t iii=0; iii<list->size(); ++iii) {
info.nativeFormats.push_back(audio::getFormatFromString(list->getStringValue(iii, "???")));
}
}
info.isDefault = doc.getBooleanValue("default", false);
/*
+ " sample-rate:[8000,16000,24000,32000,48000,96000],\n"
+ " channels=[front-left,front-right],\n"
+ " format:[int16]\n"
*/
//return retString;
return info;
}
private:
//AndroidAudioCallback m_audioCallBack;
//void* m_audioCallBackUserData;
public:
int32_t open(uint32_t _idDevice,
audio::orchestra::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
const audio::orchestra::StreamOptions& _options) {
ATA_DEBUG("C->java : audio open device");
int status;
if(!java_attach_current_thread(&status)) {
return -1;
}
//Call java ...
jboolean ret = m_JavaVirtualMachinePointer->CallBooleanMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioOpenDevice, _idDevice, _sampleRate, _channels, /*_format*/ 1);
// manage execption :
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
java_detach_current_thread(status);
if (bool(ret) == true) {
return 0;
}
return -1;
}
public:
enum audio::orchestra::error closeStream(int32_t _id) {
ATA_DEBUG("C->java : audio close device");
int status;
if(!java_attach_current_thread(&status)) {
return audio::orchestra::error_fail;
}
//Call java ...
jboolean ret = m_JavaVirtualMachinePointer->CallBooleanMethod(m_javaObjectOrchestraCallback, m_javaMethodOrchestraActivityAudioCloseDevice, _id);
// manage execption :
jvm_basics::checkExceptionJavaVM(m_JavaVirtualMachinePointer);
java_detach_current_thread(status);
if (bool(ret) == false) {
return audio::orchestra::error_fail;
}
return audio::orchestra::error_none;
}
enum audio::orchestra::error startStream(int32_t _id) {
return audio::orchestra::error_fail;
}
enum audio::orchestra::error stopStream(int32_t _id) {
return audio::orchestra::error_fail;
}
enum audio::orchestra::error abortStream(int32_t _id) {
return audio::orchestra::error_fail;
}
};
static std::shared_ptr<AndroidOrchestraContext> s_localContext;
static int32_t s_nbContextRequested(0);
int32_t ttttttt() {
return etk::tool::irand(0,54456);
uint32_t audio::orchestra::api::android::getDeviceCount() {
if (s_localContext == nullptr) {
return 0;
}
return s_localContext->getDeviceCount();
}
audio::orchestra::DeviceInfo audio::orchestra::api::android::getDeviceInfo(uint32_t _device) {
if (s_localContext == nullptr) {
return audio::orchestra::DeviceInfo();
}
return s_localContext->getDeviceInfo(_device);
}
int32_t audio::orchestra::api::android::open(uint32_t _device,
audio::orchestra::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
const audio::orchestra::StreamOptions& _options) {
if (s_localContext == nullptr) {
return -1;
}
return s_localContext->open(_device, _mode, _channels, _firstChannel, _sampleRate, _format, _bufferSize, _options);
}
enum audio::orchestra::error audio::orchestra::api::android::closeStream(int32_t _id) {
if (s_localContext == nullptr) {
return audio::orchestra::error_fail;
}
return s_localContext->closeStream(_id);
}
enum audio::orchestra::error audio::orchestra::api::android::startStream(int32_t _id) {
if (s_localContext == nullptr) {
return audio::orchestra::error_fail;
}
return s_localContext->startStream(_id);
}
enum audio::orchestra::error audio::orchestra::api::android::stopStream(int32_t _id) {
if (s_localContext == nullptr) {
return audio::orchestra::error_fail;
}
return s_localContext->stopStream(_id);
}
enum audio::orchestra::error audio::orchestra::api::android::abortStream(int32_t _id) {
if (s_localContext == nullptr) {
return audio::orchestra::error_fail;
}
return s_localContext->abortStream(_id);
}
extern "C" {

View File

@@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#if !defined(__AUDIO_ORCHESTRA_API_ANDROID_NATIVE_H__) && defined(ORCHESTRA_BUILD_JAVA)
#define __AUDIO_ORCHESTRA_API_ANDROID_NATIVE_H__
#include <audio/orchestra/DeviceInfo.h>
#include <audio/orchestra/mode.h>
#include <audio/orchestra/error.h>
#include <audio/orchestra/StreamOptions.h>
#include <audio/format.h>
namespace audio {
namespace orchestra {
namespace api {
namespace android {
uint32_t getDeviceCount();
audio::orchestra::DeviceInfo getDeviceInfo(uint32_t _device);
int32_t open(uint32_t _device,
audio::orchestra::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
uint32_t *_bufferSize,
const audio::orchestra::StreamOptions& _options);
enum audio::orchestra::error closeStream(int32_t _id);
enum audio::orchestra::error startStream(int32_t _id);
enum audio::orchestra::error stopStream(int32_t _id);
enum audio::orchestra::error abortStream(int32_t _id);
}
}
}
}
#endif