mirror of
https://gitee.com/openharmony/multimedia_audio_standard
synced 2024-12-11 14:46:40 +00:00
OnStateChange implementation
Signed-off-by: Vaidegi B <vaidegi.b1@huawei.com>
This commit is contained in:
parent
890cf58f00
commit
a903e10269
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_CAPTURER_CALLBACK_NAPI_H_
|
||||
#define AUDIO_CAPTURER_CALLBACK_NAPI_H_
|
||||
|
||||
#include "audio_common_napi.h"
|
||||
#include "audio_capturer.h"
|
||||
#include "napi/native_api.h"
|
||||
#include "napi/native_node_api.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
class AudioCapturerCallbackNapi : public AudioCapturerCallback {
|
||||
public:
|
||||
explicit AudioCapturerCallbackNapi(napi_env env);
|
||||
virtual ~AudioCapturerCallbackNapi();
|
||||
void SaveCallbackReference(const std::string &callbackName, napi_value callback);
|
||||
void OnStateChange(const CapturerState state) override;
|
||||
private:
|
||||
struct AudioCapturerJsCallback {
|
||||
std::shared_ptr<AutoRef> callback = nullptr;
|
||||
std::string callbackName = "unknown";
|
||||
CapturerState state;
|
||||
};
|
||||
|
||||
void OnJsCallbackStateChange(std::unique_ptr<AudioCapturerJsCallback> &jsCb);
|
||||
|
||||
std::mutex mutex_;
|
||||
napi_env env_ = nullptr;
|
||||
std::shared_ptr<AutoRef> stateChangeCallback_ = nullptr;
|
||||
};
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
#endif // AUDIO_CAPTURER_CALLBACK_NAPI_H_
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "audio_capturer_callback_napi.h"
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "audio_errors.h"
|
||||
#include "media_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
AudioCapturerCallbackNapi::AudioCapturerCallbackNapi(napi_env env)
|
||||
: env_(env)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: instance create");
|
||||
}
|
||||
|
||||
AudioCapturerCallbackNapi::~AudioCapturerCallbackNapi()
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: instance destroy");
|
||||
}
|
||||
|
||||
void AudioCapturerCallbackNapi::SaveCallbackReference(const std::string &callbackName, napi_value args)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
napi_ref callback = nullptr;
|
||||
const int32_t refCount = 1;
|
||||
napi_status status = napi_create_reference(env_, args, refCount, &callback);
|
||||
CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
|
||||
"AudioCapturerCallbackNapi: creating reference for callback fail");
|
||||
|
||||
std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
|
||||
if (callbackName == STATE_CHANGE_CALLBACK_NAME) {
|
||||
stateChangeCallback_ = cb;
|
||||
} else {
|
||||
MEDIA_ERR_LOG("AudioCapturerCallbackNapi: Unknown callback type: %{public}s", callbackName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCapturerCallbackNapi::OnStateChange(const CapturerState state)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: OnStateChange is called");
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: state: %{public}d", state);
|
||||
CHECK_AND_RETURN_LOG(stateChangeCallback_ != nullptr, "Cannot find the reference of stateChange callback");
|
||||
|
||||
std::unique_ptr<AudioCapturerJsCallback> cb = std::make_unique<AudioCapturerJsCallback>();
|
||||
CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
|
||||
cb->callback = stateChangeCallback_;
|
||||
cb->callbackName = STATE_CHANGE_CALLBACK_NAME;
|
||||
cb->state = state;
|
||||
return OnJsCallbackStateChange(cb);
|
||||
}
|
||||
|
||||
void AudioCapturerCallbackNapi::OnJsCallbackStateChange(std::unique_ptr<AudioCapturerJsCallback> &jsCb)
|
||||
{
|
||||
uv_loop_s *loop = nullptr;
|
||||
napi_get_uv_event_loop(env_, &loop);
|
||||
if (loop == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uv_work_t *work = new(std::nothrow) uv_work_t;
|
||||
if (work == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioCapturerCallbackNapi: OnJsCallbackStateChange: No memory");
|
||||
return;
|
||||
}
|
||||
work->data = reinterpret_cast<void *>(jsCb.get());
|
||||
|
||||
int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
|
||||
// Js Thread
|
||||
AudioCapturerJsCallback *event = reinterpret_cast<AudioCapturerJsCallback *>(work->data);
|
||||
std::string request = event->callbackName;
|
||||
napi_env env = event->callback->env_;
|
||||
napi_ref callback = event->callback->cb_;
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
|
||||
do {
|
||||
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
|
||||
|
||||
napi_value jsCallback = nullptr;
|
||||
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
|
||||
request.c_str());
|
||||
|
||||
// Call back function
|
||||
napi_value args[1] = { nullptr };
|
||||
nstatus = napi_create_int32(env, event->state, &args[0]);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
|
||||
"%{public}s fail to create Interrupt callback", request.c_str());
|
||||
|
||||
const size_t argCount = 1;
|
||||
napi_value result = nullptr;
|
||||
nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call Interrupt callback", request.c_str());
|
||||
} while (0);
|
||||
delete event;
|
||||
delete work;
|
||||
});
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Failed to execute libuv work queue");
|
||||
delete work;
|
||||
} else {
|
||||
jsCb.release();
|
||||
}
|
||||
}
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
@ -14,13 +14,15 @@
|
||||
*/
|
||||
|
||||
#include "audio_capturer_napi.h"
|
||||
#include "audio_capturer_callback_napi.h"
|
||||
#include "audio_errors.h"
|
||||
#include "audio_manager_napi.h"
|
||||
#include "audio_parameters_napi.h"
|
||||
#include "capturer_period_position_callback_napi.h"
|
||||
#include "capturer_position_callback_napi.h"
|
||||
|
||||
#include "hilog/log.h"
|
||||
|
||||
#include "media_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
using namespace std;
|
||||
@ -42,9 +44,6 @@ namespace {
|
||||
const int PARAM1 = 1;
|
||||
const int PARAM2 = 2;
|
||||
|
||||
const int ERROR = -1;
|
||||
const int SUCCESS = 0;
|
||||
|
||||
constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioCapturerNapi"};
|
||||
|
||||
const std::string MARK_REACH_CALLBACK_NAME = "markReach";
|
||||
@ -208,23 +207,25 @@ napi_value AudioCapturerNapi::Construct(napi_env env, napi_callback_info info)
|
||||
|
||||
GET_PARAMS(env, info, ARGS_TWO);
|
||||
|
||||
unique_ptr<AudioCapturerNapi> obj = make_unique<AudioCapturerNapi>();
|
||||
if (obj != nullptr) {
|
||||
obj->env_ = env;
|
||||
obj->sourceType_ = sAudioCapturerOptions_->capturerInfo.sourceType;
|
||||
obj->capturerFlags_ = sAudioCapturerOptions_->capturerInfo.capturerFlags;
|
||||
obj->audioCapturer_ = AudioCapturer::Create(*sAudioCapturerOptions_);
|
||||
if (obj->audioCapturer_ == nullptr) {
|
||||
HiLog::Error(LABEL, "Failed to create capturer object from native");
|
||||
return result;
|
||||
}
|
||||
unique_ptr<AudioCapturerNapi> capturerNapi = make_unique<AudioCapturerNapi>();
|
||||
CHECK_AND_RETURN_RET_LOG(capturerNapi != nullptr, result, "No memory");
|
||||
capturerNapi->env_ = env;
|
||||
capturerNapi->sourceType_ = sAudioCapturerOptions_->capturerInfo.sourceType;
|
||||
capturerNapi->capturerFlags_ = sAudioCapturerOptions_->capturerInfo.capturerFlags;
|
||||
|
||||
status = napi_wrap(env, thisVar, static_cast<void*>(obj.get()),
|
||||
AudioCapturerNapi::Destructor, nullptr, &(obj->wrapper_));
|
||||
if (status == napi_ok) {
|
||||
obj.release();
|
||||
return thisVar;
|
||||
}
|
||||
capturerNapi->audioCapturer_ = AudioCapturer::Create(*sAudioCapturerOptions_);
|
||||
CHECK_AND_RETURN_RET_LOG(capturerNapi->audioCapturer_ != nullptr, result, "Capturer Create failed");
|
||||
|
||||
if (capturerNapi->callbackNapi_ == nullptr) {
|
||||
capturerNapi->callbackNapi_ = std::make_shared<AudioCapturerCallbackNapi>(env);
|
||||
(void)capturerNapi->audioCapturer_->SetCapturerCallback(capturerNapi->callbackNapi_);
|
||||
}
|
||||
|
||||
status = napi_wrap(env, thisVar, static_cast<void*>(capturerNapi.get()),
|
||||
AudioCapturerNapi::Destructor, nullptr, &(capturerNapi->wrapper_));
|
||||
if (status == napi_ok) {
|
||||
capturerNapi.release();
|
||||
return thisVar;
|
||||
}
|
||||
|
||||
HiLog::Error(LABEL, "Failed in AudioCapturerNapi::Construct()!");
|
||||
@ -432,7 +433,7 @@ void AudioCapturerNapi::VoidAsyncCallbackComplete(napi_env env, napi_status stat
|
||||
}
|
||||
CommonCallbackRoutine(env, asyncContext, valueParam);
|
||||
} else {
|
||||
HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
|
||||
HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -916,43 +917,29 @@ napi_value AudioCapturerNapi::Release(napi_env env, napi_callback_info info)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Function to read string argument from napi_value
|
||||
static string GetStringArgument(napi_env env, napi_value value)
|
||||
{
|
||||
napi_status status;
|
||||
string strValue = "";
|
||||
size_t bufLength = 0;
|
||||
char *buffer = nullptr;
|
||||
|
||||
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
|
||||
if (status == napi_ok && bufLength > 0) {
|
||||
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
|
||||
if (buffer != nullptr) {
|
||||
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
|
||||
if (status == napi_ok) {
|
||||
strValue = buffer;
|
||||
}
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value undefinedResult = nullptr;
|
||||
napi_get_undefined(env, &undefinedResult);
|
||||
|
||||
const size_t minArgCount = 3;
|
||||
size_t argCount = minArgCount;
|
||||
napi_value args[minArgCount] = { nullptr, nullptr, nullptr };
|
||||
const size_t maxArgCount = 3;
|
||||
size_t argCount = maxArgCount;
|
||||
napi_value args[maxArgCount] = { nullptr, nullptr, nullptr };
|
||||
napi_value jsThis = nullptr;
|
||||
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
|
||||
args[PARAM2] == nullptr) {
|
||||
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
|
||||
if (argCount == maxArgCount - 1) { // 2 args on api
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr) {
|
||||
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
|
||||
return undefinedResult;
|
||||
}
|
||||
} else if (argCount == maxArgCount) { // mark/position reach
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
|
||||
args[PARAM2] == nullptr) {
|
||||
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
|
||||
return undefinedResult;
|
||||
}
|
||||
} else {
|
||||
MEDIA_DEBUG_LOG("AudioCapturerNapi:: on called with wrong number of args");
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
@ -963,16 +950,21 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
|
||||
|
||||
napi_valuetype valueType0 = napi_undefined;
|
||||
napi_valuetype valueType1 = napi_undefined;
|
||||
napi_valuetype valueType2 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string
|
||||
|| napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|
||||
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
|
||||
|
||||
// Check value type of PARAM0
|
||||
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
std::string callbackName = GetStringArgument(env, args[0]);
|
||||
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
|
||||
HiLog::Info(LABEL, "AudioCapturerNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType2 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|
||||
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
int64_t markPosition = 0;
|
||||
napi_get_value_int64(env, args[PARAM1], &markPosition);
|
||||
if (markPosition <= 0) {
|
||||
@ -995,7 +987,15 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
|
||||
std::static_pointer_cast<CapturerPositionCallbackNapi>(capturerNapi->positionCBNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM2]);
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
} else if (!callbackName.compare(PERIOD_REACH_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType2 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|
||||
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
int64_t frameCount = 0;
|
||||
napi_get_value_int64(env, args[PARAM1], &frameCount);
|
||||
if (frameCount <= 0) {
|
||||
@ -1018,6 +1018,28 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
|
||||
std::static_pointer_cast<CapturerPeriodPositionCallbackNapi>(capturerNapi->periodPositionCBNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM2]);
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
// Two args on api call
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(capturerNapi->callbackNapi_ != nullptr, undefinedResult,
|
||||
"AudioCapturerNapi: callbackNapi_ is nullptr");
|
||||
|
||||
std::shared_ptr<AudioCapturerCallbackNapi> cb =
|
||||
std::static_pointer_cast<AudioCapturerCallbackNapi>(capturerNapi->callbackNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM1]);
|
||||
if (!callbackName.compare(STATE_CHANGE_CALLBACK_NAME)) {
|
||||
if (capturerNapi->audioCapturer_ != nullptr) {
|
||||
CapturerState state = capturerNapi->audioCapturer_->GetStatus();
|
||||
if (state == CAPTURER_PREPARED) {
|
||||
capturerNapi->callbackNapi_->OnStateChange(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
@ -1048,7 +1070,7 @@ napi_value AudioCapturerNapi::Off(napi_env env, napi_callback_info info)
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
std::string callbackName = GetStringArgument(env, args[0]);
|
||||
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
|
||||
HiLog::Info(LABEL, "AudioCapturerNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
|
||||
if (capturerNapi->positionCBNapi_ != nullptr) {
|
||||
@ -1240,7 +1262,7 @@ napi_value AudioCapturerNapi::CreateAudioCapturerWrapper(napi_env env, unique_pt
|
||||
return result;
|
||||
}
|
||||
}
|
||||
HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
|
||||
HiLog::Error(LABEL, "Failed in CreateAudioCapturerWrapper, %{public}d", status);
|
||||
}
|
||||
|
||||
napi_get_undefined(env, &result);
|
||||
|
@ -21,6 +21,18 @@
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
namespace {
|
||||
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
|
||||
const std::string STATE_CHANGE_CALLBACK_NAME = "stateChange";
|
||||
}
|
||||
|
||||
class AudioCommonNapi {
|
||||
public:
|
||||
AudioCommonNapi() = delete;
|
||||
~AudioCommonNapi() = delete;
|
||||
static std::string GetStringArgument(napi_env env, napi_value value);
|
||||
};
|
||||
|
||||
struct AutoRef {
|
||||
AutoRef(napi_env env, napi_ref cb)
|
||||
: env_(env), cb_(cb)
|
||||
|
40
frameworks/js/napi/audio_common/src/audio_common_napi.cpp
Normal file
40
frameworks/js/napi/audio_common/src/audio_common_napi.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "audio_common_napi.h"
|
||||
#include "media_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
std::string AudioCommonNapi::GetStringArgument(napi_env env, napi_value value)
|
||||
{
|
||||
std::string strValue = "";
|
||||
size_t bufLength = 0;
|
||||
napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
|
||||
if (status == napi_ok && bufLength > 0 && bufLength < PATH_MAX) {
|
||||
char *buffer = (char *)malloc((bufLength + 1) * sizeof(char));
|
||||
CHECK_AND_RETURN_RET_LOG(buffer != nullptr, strValue, "no memory");
|
||||
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
|
||||
if (status == napi_ok) {
|
||||
MEDIA_DEBUG_LOG("argument = %{public}s", buffer);
|
||||
strValue = buffer;
|
||||
}
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
return strValue;
|
||||
}
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
@ -16,6 +16,7 @@
|
||||
#include "audio_manager_napi.h"
|
||||
|
||||
#include "audio_capturer_napi.h"
|
||||
#include "audio_common_napi.h"
|
||||
#include "audio_device_descriptor_napi.h"
|
||||
#include "audio_errors.h"
|
||||
#include "audio_parameters_napi.h"
|
||||
@ -673,30 +674,6 @@ napi_value AudioManagerNapi::GetAudioManager(napi_env env, napi_callback_info in
|
||||
return AudioManagerNapi::CreateAudioManagerWrapper(env);
|
||||
}
|
||||
|
||||
// Function to read string argument from napi_value
|
||||
static string GetStringArgument(napi_env env, napi_value value)
|
||||
{
|
||||
napi_status status;
|
||||
string strValue = "";
|
||||
size_t bufLength = 0;
|
||||
char *buffer = nullptr;
|
||||
|
||||
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
|
||||
if (status == napi_ok && bufLength > 0) {
|
||||
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
|
||||
if (buffer != nullptr) {
|
||||
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
|
||||
if (status == napi_ok) {
|
||||
strValue = buffer;
|
||||
}
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
static void CommonCallbackRoutine(napi_env env, AudioManagerAsyncContext* &asyncContext, const napi_value &valueParam)
|
||||
{
|
||||
napi_value result[ARGS_TWO] = {0};
|
||||
@ -1463,9 +1440,9 @@ napi_value AudioManagerNapi::SetAudioParameter(napi_env env, napi_callback_info
|
||||
napi_typeof(env, argv[i], &valueType);
|
||||
|
||||
if (i == PARAM0 && valueType == napi_string) {
|
||||
asyncContext->key = GetStringArgument(env, argv[i]);
|
||||
asyncContext->key = AudioCommonNapi::GetStringArgument(env, argv[i]);
|
||||
} else if (i == PARAM1 && valueType == napi_string) {
|
||||
asyncContext->valueStr = GetStringArgument(env, argv[i]);
|
||||
asyncContext->valueStr = AudioCommonNapi::GetStringArgument(env, argv[i]);
|
||||
} else if (i == PARAM2 && valueType == napi_function) {
|
||||
napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
|
||||
break;
|
||||
@ -1524,7 +1501,7 @@ napi_value AudioManagerNapi::GetAudioParameter(napi_env env, napi_callback_info
|
||||
napi_typeof(env, argv[i], &valueType);
|
||||
|
||||
if (i == PARAM0 && valueType == napi_string) {
|
||||
asyncContext->key = GetStringArgument(env, argv[i]);
|
||||
asyncContext->key = AudioCommonNapi::GetStringArgument(env, argv[i]);
|
||||
} else if (i == PARAM1 && valueType == napi_function) {
|
||||
napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
|
||||
break;
|
||||
@ -1934,8 +1911,8 @@ napi_value AudioManagerNapi::On(napi_env env, napi_callback_info info)
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
std::string callbackName = GetStringArgument(env, args[0]);
|
||||
MEDIA_INFO_LOG("AudioManagerNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
|
||||
MEDIA_DEBUG_LOG("AudioManagerNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
if (!callbackName.compare(RINGERMODE_CALLBACK_NAME)) {
|
||||
if (managerNapi->ringerModecallbackNapi_ == nullptr) {
|
||||
managerNapi->ringerModecallbackNapi_ = std::make_shared<AudioRingerModeCallbackNapi>(env);
|
||||
|
@ -13,8 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_MANAGER_CALLBACK_NAPI_H_
|
||||
#define AUDIO_MANAGER_CALLBACK_NAPI_H_
|
||||
#ifndef AUDIO_RENDERER_CALLBACK_NAPI_H_
|
||||
#define AUDIO_RENDERER_CALLBACK_NAPI_H_
|
||||
|
||||
#include "audio_common_napi.h"
|
||||
#include "audio_renderer.h"
|
||||
@ -29,20 +29,23 @@ public:
|
||||
virtual ~AudioRendererCallbackNapi();
|
||||
void SaveCallbackReference(const std::string &callbackName, napi_value callback);
|
||||
void OnInterrupt(const InterruptEvent &interruptEvent) override;
|
||||
|
||||
void OnStateChange(const RendererState state) override;
|
||||
private:
|
||||
struct AudioRendererJsCallback {
|
||||
std::shared_ptr<AutoRef> callback = nullptr;
|
||||
std::string callbackName = "unknown";
|
||||
InterruptEvent interruptEvent;
|
||||
RendererState state;
|
||||
};
|
||||
|
||||
void OnJsCallbackInterrupt(std::unique_ptr<AudioRendererJsCallback> &jsCb);
|
||||
void OnJsCallbackStateChange(std::unique_ptr<AudioRendererJsCallback> &jsCb);
|
||||
|
||||
std::mutex mutex_;
|
||||
napi_env env_ = nullptr;
|
||||
std::shared_ptr<AutoRef> interruptCallback_ = nullptr;
|
||||
std::shared_ptr<AutoRef> stateChangeCallback_ = nullptr;
|
||||
};
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
#endif // AUDIO_MANAGER_CALLBACK_NAPI_H_
|
||||
#endif // AUDIO_RENDERER_CALLBACK_NAPI_H_
|
||||
|
@ -20,10 +20,6 @@
|
||||
#include "audio_errors.h"
|
||||
#include "media_log.h"
|
||||
|
||||
namespace {
|
||||
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
AudioRendererCallbackNapi::AudioRendererCallbackNapi(napi_env env)
|
||||
@ -49,6 +45,8 @@ void AudioRendererCallbackNapi::SaveCallbackReference(const std::string &callbac
|
||||
std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
|
||||
if (callbackName == INTERRUPT_CALLBACK_NAME) {
|
||||
interruptCallback_ = cb;
|
||||
} else if (callbackName == STATE_CHANGE_CALLBACK_NAME) {
|
||||
stateChangeCallback_ = cb;
|
||||
} else {
|
||||
MEDIA_ERR_LOG("AudioRendererCallbackNapi: Unknown callback type: %{public}s", callbackName.c_str());
|
||||
}
|
||||
@ -108,7 +106,7 @@ void AudioRendererCallbackNapi::OnJsCallbackInterrupt(std::unique_ptr<AudioRende
|
||||
napi_ref callback = event->callback->cb_;
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
|
||||
do {
|
||||
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
|
||||
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
|
||||
|
||||
napi_value jsCallback = nullptr;
|
||||
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
|
||||
@ -136,5 +134,72 @@ void AudioRendererCallbackNapi::OnJsCallbackInterrupt(std::unique_ptr<AudioRende
|
||||
jsCb.release();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRendererCallbackNapi::OnStateChange(const RendererState state)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: OnStateChange is called");
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: state: %{public}d", state);
|
||||
CHECK_AND_RETURN_LOG(stateChangeCallback_ != nullptr, "Cannot find the reference of stateChange callback");
|
||||
|
||||
std::unique_ptr<AudioRendererJsCallback> cb = std::make_unique<AudioRendererJsCallback>();
|
||||
CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
|
||||
cb->callback = stateChangeCallback_;
|
||||
cb->callbackName = STATE_CHANGE_CALLBACK_NAME;
|
||||
cb->state = state;
|
||||
return OnJsCallbackStateChange(cb);
|
||||
}
|
||||
|
||||
void AudioRendererCallbackNapi::OnJsCallbackStateChange(std::unique_ptr<AudioRendererJsCallback> &jsCb)
|
||||
{
|
||||
uv_loop_s *loop = nullptr;
|
||||
napi_get_uv_event_loop(env_, &loop);
|
||||
if (loop == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uv_work_t *work = new(std::nothrow) uv_work_t;
|
||||
if (work == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioRendererCallbackNapi: OnJsCallbackStateChange: No memory");
|
||||
return;
|
||||
}
|
||||
work->data = reinterpret_cast<void *>(jsCb.get());
|
||||
|
||||
int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
|
||||
// Js Thread
|
||||
AudioRendererJsCallback *event = reinterpret_cast<AudioRendererJsCallback *>(work->data);
|
||||
std::string request = event->callbackName;
|
||||
napi_env env = event->callback->env_;
|
||||
napi_ref callback = event->callback->cb_;
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
|
||||
do {
|
||||
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
|
||||
|
||||
napi_value jsCallback = nullptr;
|
||||
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
|
||||
request.c_str());
|
||||
|
||||
// Call back function
|
||||
napi_value args[1] = { nullptr };
|
||||
nstatus = napi_create_int32(env, event->state, &args[0]);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
|
||||
"%{public}s fail to create Interrupt callback", request.c_str());
|
||||
|
||||
const size_t argCount = 1;
|
||||
napi_value result = nullptr;
|
||||
nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
|
||||
CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call Interrupt callback", request.c_str());
|
||||
} while (0);
|
||||
delete event;
|
||||
delete work;
|
||||
});
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Failed to execute libuv work queue");
|
||||
delete work;
|
||||
} else {
|
||||
jsCb.release();
|
||||
}
|
||||
}
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "renderer_period_position_callback_napi.h"
|
||||
#include "renderer_position_callback_napi.h"
|
||||
|
||||
#include "audio_common_napi.h"
|
||||
#include "audio_errors.h"
|
||||
#include "audio_manager_napi.h"
|
||||
#include "audio_parameters_napi.h"
|
||||
@ -51,7 +52,6 @@ namespace {
|
||||
|
||||
constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioRendererNapi"};
|
||||
|
||||
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
|
||||
const std::string MARK_REACH_CALLBACK_NAME = "markReach";
|
||||
const std::string PERIOD_REACH_CALLBACK_NAME = "periodReach";
|
||||
|
||||
@ -422,11 +422,12 @@ napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_status status;
|
||||
napi_value result = nullptr;
|
||||
napi_get_undefined(env, &result);
|
||||
|
||||
GET_PARAMS(env, info, ARGS_TWO);
|
||||
|
||||
unique_ptr<AudioRendererNapi> rendererNapi = make_unique<AudioRendererNapi>();
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, nullptr, "No memory");
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, result, "No memory");
|
||||
|
||||
rendererNapi->env_ = env;
|
||||
rendererNapi->contentType_ = sAudioRendererOptions_->rendererInfo.contentType;
|
||||
@ -434,7 +435,7 @@ napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
|
||||
rendererNapi->rendererFlags_ = sAudioRendererOptions_->rendererInfo.rendererFlags;
|
||||
|
||||
rendererNapi->audioRenderer_ = AudioRenderer::Create(*sAudioRendererOptions_);
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, nullptr, "No memory");
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, result, "Renderer Create failed");
|
||||
|
||||
if (rendererNapi->callbackNapi_ == nullptr) {
|
||||
rendererNapi->callbackNapi_ = std::make_shared<AudioRendererCallbackNapi>(env);
|
||||
@ -1646,30 +1647,6 @@ napi_value AudioRendererNapi::GetState(napi_env env, napi_callback_info info)
|
||||
return jsResult;
|
||||
}
|
||||
|
||||
// Function to read string argument from napi_value
|
||||
static string GetStringArgument(napi_env env, napi_value value)
|
||||
{
|
||||
napi_status status;
|
||||
string strValue = "";
|
||||
size_t bufLength = 0;
|
||||
char *buffer = nullptr;
|
||||
|
||||
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
|
||||
if (status == napi_ok && bufLength > 0) {
|
||||
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
|
||||
if (buffer != nullptr) {
|
||||
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
|
||||
if (status == napi_ok) {
|
||||
strValue = buffer;
|
||||
}
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value undefinedResult = nullptr;
|
||||
@ -1680,17 +1657,20 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
|
||||
napi_value args[maxArgCount] = { nullptr, nullptr, nullptr };
|
||||
napi_value jsThis = nullptr;
|
||||
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
|
||||
if (argCount == maxArgCount - 1) { // onInterrupt
|
||||
if (argCount == maxArgCount - 1) { // 2 args on api
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr) {
|
||||
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
|
||||
return undefinedResult;
|
||||
}
|
||||
} else { // mark/position reach
|
||||
} else if (argCount == maxArgCount) { // mark/position reach
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
|
||||
args[PARAM2] == nullptr) {
|
||||
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
|
||||
return undefinedResult;
|
||||
}
|
||||
} else {
|
||||
MEDIA_DEBUG_LOG("AudioRendererNapi:: on called with wrong number of args");
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
AudioRendererNapi *rendererNapi = nullptr;
|
||||
@ -1699,29 +1679,19 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
|
||||
NAPI_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, "audio renderer instance is null.");
|
||||
|
||||
napi_valuetype valueType0 = napi_undefined;
|
||||
napi_valuetype valueType1 = napi_undefined;
|
||||
|
||||
// Check value type of PARAM0
|
||||
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
std::string callbackName = GetStringArgument(env, args[0]);
|
||||
MEDIA_DEBUG_LOG("AudioRenderNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
if (!callbackName.compare(INTERRUPT_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType1 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, undefinedResult,
|
||||
"AudioRendererNapi: callbackNapi_ is nullptr");
|
||||
std::shared_ptr<AudioRendererCallbackNapi> cb =
|
||||
std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM1]);
|
||||
} else if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType1 = napi_undefined;
|
||||
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
|
||||
HiLog::Info(LABEL, "AudioRendererNapi: callbackName: %{public}s", callbackName.c_str());
|
||||
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType2 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|
||||
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
|
||||
MEDIA_DEBUG_LOG("AudioRenderNapi: On wrong parameters");
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
@ -1733,23 +1703,23 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
|
||||
}
|
||||
|
||||
if (rendererNapi->positionCBNapi_ == nullptr) {
|
||||
MEDIA_DEBUG_LOG("AudioRenderNapi: positionCBNapi_ is null");
|
||||
rendererNapi->positionCBNapi_ = std::make_shared<RendererPositionCallbackNapi>(env);
|
||||
int32_t ret = rendererNapi->audioRenderer_->SetRendererPositionCallback(markPosition,
|
||||
rendererNapi->positionCBNapi_);
|
||||
if (ret) {
|
||||
MEDIA_ERR_LOG("AudioRendererNapi: SetRendererPositionCallback Failed");
|
||||
HiLog::Error(LABEL, "AudioRendererNapi: SetRendererPositionCallback Failed");
|
||||
return undefinedResult;
|
||||
} else {
|
||||
MEDIA_DEBUG_LOG("AudioRendererNapi: SetRendererPositionCallback Success");
|
||||
HiLog::Debug(LABEL, "AudioRendererNapi: SetRendererPositionCallback Success");
|
||||
}
|
||||
|
||||
std::shared_ptr<RendererPositionCallbackNapi> cb =
|
||||
std::static_pointer_cast<RendererPositionCallbackNapi>(rendererNapi->positionCBNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM2]);
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
} else if (!callbackName.compare(PERIOD_REACH_CALLBACK_NAME)) {
|
||||
napi_valuetype valueType1 = napi_undefined;
|
||||
napi_valuetype valueType2 = napi_undefined;
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|
||||
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
|
||||
@ -1768,29 +1738,52 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
|
||||
int32_t ret = rendererNapi->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
|
||||
rendererNapi->periodPositionCBNapi_);
|
||||
if (ret) {
|
||||
MEDIA_ERR_LOG("AudioRendererNapi: SetRendererPeriodPositionCallback Failed");
|
||||
HiLog::Error(LABEL, "AudioRendererNapi: SetRendererPeriodPositionCallback Failed");
|
||||
return undefinedResult;
|
||||
} else {
|
||||
MEDIA_DEBUG_LOG("AudioRendererNapi: SetRendererPeriodPositionCallback Success");
|
||||
HiLog::Debug(LABEL, "AudioRendererNapi: SetRendererPeriodPositionCallback Success");
|
||||
}
|
||||
|
||||
std::shared_ptr<RendererPeriodPositionCallbackNapi> cb =
|
||||
std::static_pointer_cast<RendererPeriodPositionCallbackNapi>(rendererNapi->periodPositionCBNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM2]);
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
// Two args on api call
|
||||
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, undefinedResult,
|
||||
"AudioRendererNapi: callbackNapi_ is nullptr");
|
||||
|
||||
std::shared_ptr<AudioRendererCallbackNapi> cb =
|
||||
std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
|
||||
cb->SaveCallbackReference(callbackName, args[PARAM1]);
|
||||
if (!callbackName.compare(STATE_CHANGE_CALLBACK_NAME)) {
|
||||
if (rendererNapi->audioRenderer_ != nullptr) {
|
||||
RendererState state = rendererNapi->audioRenderer_->GetStatus();
|
||||
if (state == RENDERER_PREPARED) {
|
||||
rendererNapi->callbackNapi_->OnStateChange(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
|
||||
napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value undefinedResult = nullptr;
|
||||
napi_get_undefined(env, &undefinedResult);
|
||||
|
||||
const size_t maxArgCount = 1;
|
||||
size_t argCount = maxArgCount;
|
||||
napi_value args[maxArgCount] = { nullptr };
|
||||
const size_t minArgCount = 1;
|
||||
size_t argCount = minArgCount;
|
||||
napi_value args[minArgCount] = { nullptr };
|
||||
napi_value jsThis = nullptr;
|
||||
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
|
||||
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr) {
|
||||
@ -1808,7 +1801,7 @@ napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
|
||||
return undefinedResult;
|
||||
}
|
||||
|
||||
std::string callbackName = GetStringArgument(env, args[0]);
|
||||
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
|
||||
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
|
||||
if (rendererNapi->positionCBNapi_ != nullptr) {
|
||||
MEDIA_DEBUG_LOG("AudioRenderNapi: positionCBNapi_ is not null");
|
||||
|
@ -25,6 +25,7 @@ class AudioCapturerPrivate : public AudioCapturer {
|
||||
public:
|
||||
int32_t GetFrameCount(uint32_t &frameCount) const override;
|
||||
int32_t SetParams(const AudioCapturerParams params) const override;
|
||||
int32_t SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback) override;
|
||||
int32_t GetParams(AudioCapturerParams ¶ms) const override;
|
||||
int32_t GetCapturerInfo(AudioCapturerInfo &capturerInfo) const override;
|
||||
int32_t GetStreamInfo(AudioStreamInfo &streamInfo) const override;
|
||||
@ -43,11 +44,23 @@ public:
|
||||
const std::shared_ptr<CapturerPeriodPositionCallback> &callback) override;
|
||||
void UnsetCapturerPeriodPositionCallback() override;
|
||||
|
||||
std::unique_ptr<AudioStream> audioCapturer;
|
||||
std::shared_ptr<AudioStream> audioStream_;
|
||||
AudioCapturerInfo capturerInfo_ = {};
|
||||
|
||||
explicit AudioCapturerPrivate(AudioStreamType audioStreamType);
|
||||
virtual ~AudioCapturerPrivate();
|
||||
private:
|
||||
std::shared_ptr<AudioStreamCallback> audioStreamCallback_ = nullptr;
|
||||
};
|
||||
|
||||
class AudioStreamCallbackCapturer : public AudioStreamCallback {
|
||||
public:
|
||||
virtual ~AudioStreamCallbackCapturer() = default;
|
||||
|
||||
void OnStateChange(const State state) override;
|
||||
void SaveCallback(const std::weak_ptr<AudioCapturerCallback> &callback);
|
||||
private:
|
||||
std::weak_ptr<AudioCapturerCallback> callback_;
|
||||
};
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "audio_capturer_private.h"
|
||||
#include "audio_errors.h"
|
||||
#include "audio_stream.h"
|
||||
#include "media_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
@ -65,12 +66,12 @@ std::unique_ptr<AudioCapturer> AudioCapturer::Create(const AudioCapturerOptions
|
||||
|
||||
AudioCapturerPrivate::AudioCapturerPrivate(AudioStreamType audioStreamType)
|
||||
{
|
||||
audioCapturer = std::make_unique<AudioStream>(audioStreamType, AUDIO_MODE_RECORD);
|
||||
audioStream_ = std::make_shared<AudioStream>(audioStreamType, AUDIO_MODE_RECORD);
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::GetFrameCount(uint32_t &frameCount) const
|
||||
{
|
||||
return audioCapturer->GetFrameCount(frameCount);
|
||||
return audioStream_->GetFrameCount(frameCount);
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) const
|
||||
@ -81,13 +82,43 @@ int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) const
|
||||
audioStreamParams.channels = params.audioChannel;
|
||||
audioStreamParams.encoding = params.audioEncoding;
|
||||
|
||||
return audioCapturer->SetAudioStreamInfo(audioStreamParams);
|
||||
return audioStream_->SetAudioStreamInfo(audioStreamParams);
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback)
|
||||
{
|
||||
// If the client is using the deprecated SetParams API. SetCapturerCallback must be invoked, after SetParams.
|
||||
// In general, callbacks can only be set after the capturer state is PREPARED.
|
||||
CapturerState state = GetStatus();
|
||||
if (state == CAPTURER_NEW || state == CAPTURER_RELEASED) {
|
||||
MEDIA_DEBUG_LOG("AudioCapturerPrivate::SetCapturerCallback ncorrect state:%{public}d to register cb", state);
|
||||
return ERR_ILLEGAL_STATE;
|
||||
}
|
||||
if (callback == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioCapturerPrivate::SetCapturerCallback callback param is null");
|
||||
return ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Save and Set reference for stream callback. Order is important here.
|
||||
if (audioStreamCallback_ == nullptr) {
|
||||
audioStreamCallback_ = std::make_shared<AudioStreamCallbackCapturer>();
|
||||
if (audioStreamCallback_ == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioCapturerPrivate::Failed to allocate memory for audioStreamCallback_");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<AudioStreamCallbackCapturer> cbStream =
|
||||
std::static_pointer_cast<AudioStreamCallbackCapturer>(audioStreamCallback_);
|
||||
cbStream->SaveCallback(callback);
|
||||
(void)audioStream_->SetStreamCallback(audioStreamCallback_);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::GetParams(AudioCapturerParams ¶ms) const
|
||||
{
|
||||
AudioStreamParams audioStreamParams;
|
||||
int32_t result = audioCapturer->GetAudioStreamInfo(audioStreamParams);
|
||||
int32_t result = audioStream_->GetAudioStreamInfo(audioStreamParams);
|
||||
if (SUCCESS == result) {
|
||||
params.audioSampleFormat = static_cast<AudioSampleFormat>(audioStreamParams.format);
|
||||
params.samplingRate = static_cast<AudioSamplingRate>(audioStreamParams.samplingRate);
|
||||
@ -108,7 +139,7 @@ int32_t AudioCapturerPrivate::GetCapturerInfo(AudioCapturerInfo &capturerInfo) c
|
||||
int32_t AudioCapturerPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
|
||||
{
|
||||
AudioStreamParams audioStreamParams;
|
||||
int32_t result = audioCapturer->GetAudioStreamInfo(audioStreamParams);
|
||||
int32_t result = audioStream_->GetAudioStreamInfo(audioStreamParams);
|
||||
if (SUCCESS == result) {
|
||||
streamInfo.format = static_cast<AudioSampleFormat>(audioStreamParams.format);
|
||||
streamInfo.samplingRate = static_cast<AudioSamplingRate>(audioStreamParams.samplingRate);
|
||||
@ -122,67 +153,83 @@ int32_t AudioCapturerPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
|
||||
int32_t AudioCapturerPrivate::SetCapturerPositionCallback(int64_t markPosition,
|
||||
const std::shared_ptr<CapturerPositionCallback> &callback)
|
||||
{
|
||||
audioCapturer->SetCapturerPositionCallback(markPosition, callback);
|
||||
audioStream_->SetCapturerPositionCallback(markPosition, callback);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void AudioCapturerPrivate::UnsetCapturerPositionCallback()
|
||||
{
|
||||
audioCapturer->UnsetCapturerPositionCallback();
|
||||
audioStream_->UnsetCapturerPositionCallback();
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::SetCapturerPeriodPositionCallback(int64_t frameNumber,
|
||||
const std::shared_ptr<CapturerPeriodPositionCallback> &callback)
|
||||
{
|
||||
audioCapturer->SetCapturerPeriodPositionCallback(frameNumber, callback);
|
||||
audioStream_->SetCapturerPeriodPositionCallback(frameNumber, callback);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void AudioCapturerPrivate::UnsetCapturerPeriodPositionCallback()
|
||||
{
|
||||
audioCapturer->UnsetCapturerPeriodPositionCallback();
|
||||
audioStream_->UnsetCapturerPeriodPositionCallback();
|
||||
}
|
||||
|
||||
bool AudioCapturerPrivate::Start() const
|
||||
{
|
||||
return audioCapturer->StartAudioStream();
|
||||
return audioStream_->StartAudioStream();
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::Read(uint8_t &buffer, size_t userSize, bool isBlockingRead) const
|
||||
{
|
||||
return audioCapturer->Read(buffer, userSize, isBlockingRead);
|
||||
return audioStream_->Read(buffer, userSize, isBlockingRead);
|
||||
}
|
||||
|
||||
CapturerState AudioCapturerPrivate::GetStatus() const
|
||||
{
|
||||
return (CapturerState)audioCapturer->GetState();
|
||||
return (CapturerState)audioStream_->GetState();
|
||||
}
|
||||
|
||||
bool AudioCapturerPrivate::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const
|
||||
{
|
||||
return audioCapturer->GetAudioTime(timestamp, base);
|
||||
return audioStream_->GetAudioTime(timestamp, base);
|
||||
}
|
||||
|
||||
bool AudioCapturerPrivate::Stop() const
|
||||
{
|
||||
return audioCapturer->StopAudioStream();
|
||||
return audioStream_->StopAudioStream();
|
||||
}
|
||||
|
||||
bool AudioCapturerPrivate::Flush() const
|
||||
{
|
||||
return audioCapturer->FlushAudioStream();
|
||||
return audioStream_->FlushAudioStream();
|
||||
}
|
||||
|
||||
bool AudioCapturerPrivate::Release() const
|
||||
{
|
||||
return audioCapturer->ReleaseAudioStream();
|
||||
return audioStream_->ReleaseAudioStream();
|
||||
}
|
||||
|
||||
int32_t AudioCapturerPrivate::GetBufferSize(size_t &bufferSize) const
|
||||
{
|
||||
return audioCapturer->GetBufferSize(bufferSize);
|
||||
return audioStream_->GetBufferSize(bufferSize);
|
||||
}
|
||||
|
||||
void AudioStreamCallbackCapturer::SaveCallback(const std::weak_ptr<AudioCapturerCallback> &callback)
|
||||
{
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
void AudioStreamCallbackCapturer::OnStateChange(const State state)
|
||||
{
|
||||
std::shared_ptr<AudioCapturerCallback> cb = callback_.lock();
|
||||
if (cb == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioStreamCallbackCapturer::OnStateChange cb == nullptr.");
|
||||
return;
|
||||
}
|
||||
|
||||
cb->OnStateChange(static_cast<CapturerState>(state));
|
||||
}
|
||||
|
||||
std::vector<AudioSampleFormat> AudioCapturer::GetSupportedFormats()
|
||||
|
@ -63,8 +63,8 @@ public:
|
||||
~AudioRendererPrivate();
|
||||
|
||||
private:
|
||||
std::shared_ptr<AudioRendererCallback> callback_ = nullptr;
|
||||
std::shared_ptr<AudioInterruptCallback> audioInterruptCallback_ = nullptr;
|
||||
std::shared_ptr<AudioStreamCallback> audioStreamCallback_ = nullptr;
|
||||
AudioInterrupt audioInterrupt_ =
|
||||
{STREAM_USAGE_UNKNOWN, CONTENT_TYPE_UNKNOWN, AudioStreamType::STREAM_DEFAULT, 0};
|
||||
uint32_t sessionID_ = INVALID_SESSION_ID;
|
||||
@ -91,6 +91,16 @@ private:
|
||||
bool isForceDucked_ = false;
|
||||
float instanceVolBeforeDucking_ = 0.2f;
|
||||
};
|
||||
|
||||
class AudioStreamCallbackRenderer : public AudioStreamCallback {
|
||||
public:
|
||||
virtual ~AudioStreamCallbackRenderer() = default;
|
||||
|
||||
void OnStateChange(const State state) override;
|
||||
void SaveCallback(const std::weak_ptr<AudioRendererCallback> &callback);
|
||||
private:
|
||||
std::weak_ptr<AudioRendererCallback> callback_;
|
||||
};
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
#endif // AUDIO_RENDERER_PRIVATE_H
|
||||
|
@ -40,12 +40,12 @@ std::unique_ptr<AudioRenderer> AudioRenderer::Create(AudioStreamType audioStream
|
||||
std::unique_ptr<AudioRenderer> AudioRenderer::Create(const AudioRendererOptions &rendererOptions)
|
||||
{
|
||||
ContentType contentType = rendererOptions.rendererInfo.contentType;
|
||||
CHECK_AND_RETURN_RET_LOG(contentType >= CONTENT_TYPE_SPEECH && contentType <= CONTENT_TYPE_RINGTONE, nullptr,
|
||||
CHECK_AND_RETURN_RET_LOG(contentType >= CONTENT_TYPE_UNKNOWN && contentType <= CONTENT_TYPE_RINGTONE, nullptr,
|
||||
"Invalid content type");
|
||||
|
||||
StreamUsage streamUsage = rendererOptions.rendererInfo.streamUsage;
|
||||
CHECK_AND_RETURN_RET_LOG(streamUsage >= STREAM_USAGE_MEDIA && streamUsage <= STREAM_USAGE_VOICE_ASSISTANT, nullptr,
|
||||
"Invalid stream usage");
|
||||
CHECK_AND_RETURN_RET_LOG(streamUsage >= STREAM_USAGE_UNKNOWN && streamUsage <= STREAM_USAGE_VOICE_ASSISTANT,
|
||||
nullptr, "Invalid stream usage");
|
||||
|
||||
AudioStreamType audioStreamType = AudioStream::GetStreamType(contentType, streamUsage);
|
||||
auto audioRenderer = std::make_unique<AudioRendererPrivate>(audioStreamType);
|
||||
@ -156,9 +156,11 @@ int32_t AudioRendererPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
|
||||
|
||||
int32_t AudioRendererPrivate::SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback)
|
||||
{
|
||||
// If the client is using the deprecated SetParams API. SetRendererCallback must be invoked, after SetParams.
|
||||
// In general, callbacks can only be set after the renderer state is PREPARED.
|
||||
RendererState state = GetStatus();
|
||||
if (state != RENDERER_PREPARED) {
|
||||
MEDIA_DEBUG_LOG("AudioRendererPrivate::SetRendererCallback State is not PREPARED to register callback");
|
||||
if (state == RENDERER_NEW || state == RENDERER_RELEASED) {
|
||||
MEDIA_DEBUG_LOG("AudioRendererPrivate::SetRendererCallback incorrect state:%{public}d to register cb", state);
|
||||
return ERR_ILLEGAL_STATE;
|
||||
}
|
||||
if (callback == nullptr) {
|
||||
@ -166,12 +168,28 @@ int32_t AudioRendererPrivate::SetRendererCallback(const std::shared_ptr<AudioRen
|
||||
return ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
callback_ = callback;
|
||||
|
||||
// Save reference for interrupt callback
|
||||
if (audioInterruptCallback_ == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioRendererPrivate::SetRendererCallback audioInterruptCallback_ == nullptr");
|
||||
return ERROR;
|
||||
}
|
||||
std::shared_ptr<AudioInterruptCallbackImpl> cbInterrupt =
|
||||
std::static_pointer_cast<AudioInterruptCallbackImpl>(audioInterruptCallback_);
|
||||
cbInterrupt->SaveCallback(callback);
|
||||
|
||||
// Save and Set reference for stream callback. Order is important here.
|
||||
if (audioStreamCallback_ == nullptr) {
|
||||
audioStreamCallback_ = std::make_shared<AudioStreamCallbackRenderer>();
|
||||
if (audioStreamCallback_ == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioRendererPrivate::Failed to allocate memory for audioStreamCallback_");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<AudioStreamCallbackRenderer> cbStream =
|
||||
std::static_pointer_cast<AudioStreamCallbackRenderer>(audioStreamCallback_);
|
||||
cbStream->SaveCallback(callback);
|
||||
(void)audioStream_->SetStreamCallback(audioStreamCallback_);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -463,6 +481,21 @@ void AudioInterruptCallbackImpl::OnInterrupt(const InterruptEventInternal &inter
|
||||
HandleAndNotifyForcedEvent(interruptEvent);
|
||||
}
|
||||
|
||||
void AudioStreamCallbackRenderer::SaveCallback(const std::weak_ptr<AudioRendererCallback> &callback)
|
||||
{
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
void AudioStreamCallbackRenderer::OnStateChange(const State state)
|
||||
{
|
||||
std::shared_ptr<AudioRendererCallback> cb = callback_.lock();
|
||||
if (cb == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioStreamCallbackRenderer::OnStateChange cb == nullptr.");
|
||||
return;
|
||||
}
|
||||
|
||||
cb->OnStateChange(static_cast<RendererState>(state));
|
||||
}
|
||||
|
||||
std::vector<AudioSampleFormat> AudioRenderer::GetSupportedFormats()
|
||||
{
|
||||
|
@ -25,29 +25,6 @@ enum AudioMode {
|
||||
AUDIO_MODE_RECORD
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enumerates the stream states of the current device.
|
||||
*
|
||||
* @since 1.0
|
||||
* @version 1.0
|
||||
*/
|
||||
enum State {
|
||||
/** INVALID */
|
||||
INVALID = -1,
|
||||
/** New */
|
||||
NEW,
|
||||
/** Prepared */
|
||||
PREPARED,
|
||||
/** Running */
|
||||
RUNNING,
|
||||
/** Stopped */
|
||||
STOPPED,
|
||||
/** Released */
|
||||
RELEASED,
|
||||
/** Paused */
|
||||
PAUSED
|
||||
};
|
||||
|
||||
class AudioStream : public AudioSession {
|
||||
public:
|
||||
AudioStream(AudioStreamType eStreamType, AudioMode eMode);
|
||||
@ -68,6 +45,7 @@ public:
|
||||
float GetVolume();
|
||||
int32_t SetRenderRate(AudioRendererRate renderRate);
|
||||
AudioRendererRate GetRenderRate();
|
||||
int32_t SetStreamCallback(const std::shared_ptr<AudioStreamCallback> &callback);
|
||||
|
||||
std::vector<AudioSampleFormat> GetSupportedFormats();
|
||||
std::vector<AudioChannel> GetSupportedChannels();
|
||||
|
@ -49,6 +49,8 @@ ohos_shared_library("audio_capturer") {
|
||||
|
||||
public_configs = [ ":audio_external_library_config" ]
|
||||
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
|
||||
part_name = "multimedia_audio_standard"
|
||||
subsystem_name = "multimedia"
|
||||
}
|
||||
|
@ -59,6 +59,18 @@ enum CapturerState {
|
||||
CAPTURER_RELEASED
|
||||
};
|
||||
|
||||
class AudioCapturerCallback {
|
||||
public:
|
||||
virtual ~AudioCapturerCallback() = default;
|
||||
/**
|
||||
* Called when renderer state is updated.
|
||||
*
|
||||
* @param state Indicates updated state of the capturer.
|
||||
* For details, refer enum CapturerState.
|
||||
*/
|
||||
virtual void OnStateChange(const CapturerState state) = 0;
|
||||
};
|
||||
|
||||
class CapturerPositionCallback {
|
||||
public:
|
||||
virtual ~CapturerPositionCallback() = default;
|
||||
@ -98,15 +110,6 @@ public:
|
||||
*/
|
||||
static std::unique_ptr<AudioCapturer> Create(const AudioCapturerOptions &capturerOptions);
|
||||
|
||||
/**
|
||||
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
|
||||
*
|
||||
* @param frameCount Indicates the pointer in which framecount will be written
|
||||
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets audio capture parameters.
|
||||
*
|
||||
@ -117,6 +120,18 @@ public:
|
||||
*/
|
||||
virtual int32_t SetParams(const AudioCapturerParams params) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers the capturer callback listener.
|
||||
* (1)If old SetParams(const AudioCapturerParams params) API,
|
||||
* this API must be called immediately after SetParams.
|
||||
* (2) Else if using Create(const AudioCapturerOptions &capturerOptions),
|
||||
* this API must be called immediately after Create.
|
||||
*
|
||||
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
virtual int32_t SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback) = 0;
|
||||
|
||||
/**
|
||||
* @brief Obtains audio capturer parameters.
|
||||
*
|
||||
@ -223,12 +238,21 @@ public:
|
||||
*/
|
||||
virtual int32_t GetBufferSize(size_t &bufferSize) const = 0;
|
||||
|
||||
/* @brief Obtains the number of frames required in the current condition, in bytes per sample.
|
||||
*
|
||||
* @param frameCount Indicates the pointer in which framecount will be written
|
||||
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
|
||||
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
|
||||
/**
|
||||
* @brief Registers the capturer position callback listener
|
||||
*
|
||||
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
|
||||
virtual int32_t SetCapturerPositionCallback(int64_t markPosition,
|
||||
const std::shared_ptr<CapturerPositionCallback> &callback) = 0;
|
||||
|
||||
|
@ -69,6 +69,14 @@ public:
|
||||
* For details, refer InterruptEvent struct in audio_info.h
|
||||
*/
|
||||
virtual void OnInterrupt(const InterruptEvent &interruptEvent) = 0;
|
||||
|
||||
/**
|
||||
* Called when renderer state is updated.
|
||||
*
|
||||
* @param state Indicates updated state of the renderer.
|
||||
* For details, refer RendererState enum.
|
||||
*/
|
||||
virtual void OnStateChange(const RendererState state) = 0;
|
||||
};
|
||||
|
||||
class RendererPositionCallback {
|
||||
@ -108,6 +116,7 @@ public:
|
||||
* @return Returns unique pointer to the AudioRenderer object
|
||||
*/
|
||||
static std::unique_ptr<AudioRenderer> Create(AudioStreamType audioStreamType);
|
||||
|
||||
/**
|
||||
* @brief creater renderer instance.
|
||||
*
|
||||
@ -116,14 +125,6 @@ public:
|
||||
* @return Returns unique pointer to the AudioRenderer object
|
||||
*/
|
||||
static std::unique_ptr<AudioRenderer> Create(const AudioRendererOptions &rendererOptions);
|
||||
/**
|
||||
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
|
||||
*
|
||||
* @param frameCount Indicates the reference variable in which framecount will be written
|
||||
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets audio renderer parameters.
|
||||
@ -135,6 +136,18 @@ public:
|
||||
*/
|
||||
virtual int32_t SetParams(const AudioRendererParams params) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers the renderer callback listener.
|
||||
* (1)If using old SetParams(const AudioCapturerParams params) API,
|
||||
* this API must be called immediatley after SetParams.
|
||||
* (2) Else if using Create(const AudioRendererOptions &rendererOptions),
|
||||
* this API must be called immediatley after Create.
|
||||
*
|
||||
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
virtual int32_t SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback) = 0;
|
||||
|
||||
/**
|
||||
* @brief Obtains audio renderer parameters.
|
||||
*
|
||||
@ -263,6 +276,15 @@ public:
|
||||
*/
|
||||
virtual int32_t GetBufferSize(size_t &bufferSize) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
|
||||
*
|
||||
* @param frameCount Indicates the reference variable in which framecount will be written
|
||||
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Set audio renderer descriptors
|
||||
*
|
||||
@ -313,15 +335,6 @@ public:
|
||||
*/
|
||||
virtual AudioRendererRate GetRenderRate() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers the renderer callback listener
|
||||
*
|
||||
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
|
||||
* defined in {@link audio_errors.h} otherwise.
|
||||
*/
|
||||
|
||||
virtual int32_t SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers the renderer position callback listener
|
||||
*
|
||||
|
@ -116,9 +116,9 @@ private:
|
||||
uint32_t capturerFlags_;
|
||||
napi_env env_;
|
||||
napi_ref wrapper_;
|
||||
|
||||
std::shared_ptr<CapturerPositionCallback> positionCBNapi_ = nullptr;
|
||||
std::shared_ptr<CapturerPeriodPositionCallback> periodPositionCBNapi_ = nullptr;
|
||||
std::shared_ptr<AudioCapturerCallback> callbackNapi_ = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1141,15 +1141,15 @@ declare namespace audio {
|
||||
*/
|
||||
off(type: "periodReach"): void;
|
||||
/**
|
||||
* Subscribes period reach event callback.
|
||||
* Subscribes audio state change event callback.
|
||||
* @param type Event type.
|
||||
* @param callback Callback used to listen for the audio state event
|
||||
* @return Audio state
|
||||
* @param callback Callback used to listen for the audio state change event.
|
||||
* @return AudioState
|
||||
* @since 8
|
||||
* @syscap SystemCapability.Multimedia.Audio
|
||||
* @initial
|
||||
*/
|
||||
on(type: "stateChanged", callback: Callback<AudioState>): void;
|
||||
on(type: "stateChange", callback: Callback<AudioState>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1355,17 +1355,17 @@ declare namespace audio {
|
||||
* @initial
|
||||
*/
|
||||
off(type: "periodReach"): void;
|
||||
|
||||
/**
|
||||
* Subscribes period reach event callback.
|
||||
* Subscribes audio state change event callback.
|
||||
* @param type Event type.
|
||||
* @param callback Callback used to listen for the audio state event
|
||||
* @return Audio state
|
||||
* @param callback Callback used to listen for the audio state change event.
|
||||
* @return AudioState
|
||||
* @since 8
|
||||
* @syscap SystemCapability.Multimedia.Audio
|
||||
* @initial
|
||||
*/
|
||||
on(type: "stateChanged", callback: Callback<AudioState>): void;
|
||||
on(type: "stateChange", callback: Callback<AudioState>): void;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1536,4 +1536,4 @@ declare namespace audio {
|
||||
}
|
||||
}
|
||||
|
||||
export default audio;
|
||||
export default audio;
|
||||
|
@ -46,10 +46,12 @@ ohos_shared_library("audio") {
|
||||
]
|
||||
|
||||
sources = [
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_capturer_callback_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_capturer_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_parameters_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/capturer_period_position_callback_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/capturer_position_callback_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_common/src/audio_common_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_device_descriptor_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_manager_callback_napi.cpp",
|
||||
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_manager_napi.cpp",
|
||||
|
@ -62,6 +62,41 @@ struct AudioCache {
|
||||
bool isFull;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enumerates the stream states of the current device.
|
||||
*
|
||||
* @since 1.0
|
||||
* @version 1.0
|
||||
*/
|
||||
enum State {
|
||||
/** INVALID */
|
||||
INVALID = -1,
|
||||
/** New */
|
||||
NEW,
|
||||
/** Prepared */
|
||||
PREPARED,
|
||||
/** Running */
|
||||
RUNNING,
|
||||
/** Stopped */
|
||||
STOPPED,
|
||||
/** Released */
|
||||
RELEASED,
|
||||
/** Paused */
|
||||
PAUSED
|
||||
};
|
||||
|
||||
class AudioStreamCallback {
|
||||
public:
|
||||
virtual ~AudioStreamCallback() = default;
|
||||
/**
|
||||
* Called when stream state is updated.
|
||||
*
|
||||
* @param state Indicates the InterruptEvent information needed by client.
|
||||
* For details, refer InterruptEvent struct in audio_info.h
|
||||
*/
|
||||
virtual void OnStateChange(const State state) = 0;
|
||||
};
|
||||
|
||||
class AudioRendererCallbacks {
|
||||
public:
|
||||
virtual ~AudioRendererCallbacks();
|
||||
@ -388,6 +423,8 @@ public:
|
||||
*/
|
||||
AudioRendererRate GetStreamRenderRate();
|
||||
|
||||
void SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> &callback);
|
||||
|
||||
// Audio timer callback
|
||||
virtual void OnTimeOut();
|
||||
|
||||
@ -441,6 +478,10 @@ private:
|
||||
std::vector<std::unique_ptr<std::thread>> mPositionCBThreads;
|
||||
std::vector<std::unique_ptr<std::thread>> mPeriodPositionCBThreads;
|
||||
|
||||
std::weak_ptr<AudioStreamCallback> streamCallback_;
|
||||
State state_;
|
||||
pa_stream_success_cb_t PAStreamCorkSuccessCb;
|
||||
|
||||
// To be set while using audio stream
|
||||
// functionality for callbacks
|
||||
AudioRendererCallbacks *mAudioRendererCallbacks;
|
||||
@ -495,13 +536,16 @@ private:
|
||||
void ResetPAAudioClient();
|
||||
// For setting some environment variables required while running from hap
|
||||
void SetEnv();
|
||||
int32_t CorkStream();
|
||||
|
||||
// Callbacks to be implemented
|
||||
static void PAStreamStateCb(pa_stream *stream, void *userdata);
|
||||
static void PAStreamUnderFlowCb(pa_stream *stream, void *userdata);
|
||||
static void PAContextStateCb(pa_context *context, void *userdata);
|
||||
static void PAStreamRequestCb(pa_stream *stream, size_t length, void *userdata);
|
||||
static void PAStreamCmdSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamDrainSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata);
|
||||
static void PAStreamLatencyUpdateCb(pa_stream *stream, void *userdata);
|
||||
|
@ -128,11 +128,44 @@ static size_t AlignToAudioFrameSize(size_t l, const pa_sample_spec &ss)
|
||||
return (l / fs) * fs;
|
||||
}
|
||||
|
||||
void AudioServiceClient::PAStreamCmdSuccessCb(pa_stream *stream, int32_t success, void *userdata)
|
||||
void AudioServiceClient::PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata)
|
||||
{
|
||||
AudioServiceClient *asClient = (AudioServiceClient *)userdata;
|
||||
pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
|
||||
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
|
||||
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
|
||||
|
||||
asClient->state_ = RUNNING;
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(asClient->state_);
|
||||
}
|
||||
asClient->streamCmdStatus = success;
|
||||
pa_threaded_mainloop_signal(mainLoop, 0);
|
||||
}
|
||||
|
||||
void AudioServiceClient::PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata)
|
||||
{
|
||||
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
|
||||
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
|
||||
|
||||
asClient->state_ = STOPPED;
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(asClient->state_);
|
||||
}
|
||||
asClient->streamCmdStatus = success;
|
||||
pa_threaded_mainloop_signal(mainLoop, 0);
|
||||
}
|
||||
|
||||
void AudioServiceClient::PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata)
|
||||
{
|
||||
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
|
||||
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
|
||||
|
||||
asClient->state_ = PAUSED;
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(asClient->state_);
|
||||
}
|
||||
asClient->streamCmdStatus = success;
|
||||
pa_threaded_mainloop_signal(mainLoop, 0);
|
||||
}
|
||||
@ -275,6 +308,8 @@ AudioServiceClient::AudioServiceClient()
|
||||
acache.isFull = false;
|
||||
acache.totalCacheSize = 0;
|
||||
acache.buffer = NULL;
|
||||
|
||||
PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
|
||||
}
|
||||
|
||||
void AudioServiceClient::ResetPAAudioClient()
|
||||
@ -345,6 +380,8 @@ void AudioServiceClient::ResetPAAudioClient()
|
||||
acache.writeIndex = 0;
|
||||
acache.isFull = false;
|
||||
acache.totalCacheSize = 0;
|
||||
|
||||
PAStreamCorkSuccessCb = NULL;
|
||||
}
|
||||
|
||||
AudioServiceClient::~AudioServiceClient()
|
||||
@ -638,6 +675,12 @@ int32_t AudioServiceClient::CreateStream(AudioStreamParams audioParams, AudioStr
|
||||
}
|
||||
}
|
||||
|
||||
state_ = PREPARED;
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(state_);
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("Created Stream");
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
@ -674,7 +717,7 @@ int32_t AudioServiceClient::StartStream()
|
||||
}
|
||||
|
||||
streamCmdStatus = 0;
|
||||
operation = pa_stream_cork(paStream, 0, PAStreamCmdSuccessCb, (void *)this);
|
||||
operation = pa_stream_cork(paStream, 0, PAStreamStartSuccessCb, (void *)this);
|
||||
|
||||
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
|
||||
pa_threaded_mainloop_wait(mainLoop);
|
||||
@ -694,12 +737,42 @@ int32_t AudioServiceClient::StartStream()
|
||||
|
||||
int32_t AudioServiceClient::PauseStream()
|
||||
{
|
||||
return StopStream();
|
||||
lock_guard<mutex> lock(ctrlMutex);
|
||||
PAStreamCorkSuccessCb = PAStreamPauseSuccessCb;
|
||||
int32_t ret = CorkStream();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!streamCmdStatus) {
|
||||
MEDIA_ERR_LOG("Stream Pasue Failed");
|
||||
return AUDIO_CLIENT_ERR;
|
||||
} else {
|
||||
MEDIA_INFO_LOG("Stream Pasued Successfully");
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t AudioServiceClient::StopStream()
|
||||
{
|
||||
lock_guard<mutex> lock(ctrlMutex);
|
||||
PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
|
||||
int32_t ret = CorkStream();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!streamCmdStatus) {
|
||||
MEDIA_ERR_LOG("Stream Stop Failed");
|
||||
return AUDIO_CLIENT_ERR;
|
||||
} else {
|
||||
MEDIA_INFO_LOG("Stream Stopped Successfully");
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t AudioServiceClient::CorkStream()
|
||||
{
|
||||
CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
|
||||
pa_operation *operation = NULL;
|
||||
|
||||
@ -713,7 +786,7 @@ int32_t AudioServiceClient::StopStream()
|
||||
}
|
||||
|
||||
streamCmdStatus = 0;
|
||||
operation = pa_stream_cork(paStream, 1, PAStreamCmdSuccessCb, (void *)this);
|
||||
operation = pa_stream_cork(paStream, 1, PAStreamCorkSuccessCb, (void *)this);
|
||||
|
||||
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
|
||||
pa_threaded_mainloop_wait(mainLoop);
|
||||
@ -721,13 +794,7 @@ int32_t AudioServiceClient::StopStream()
|
||||
pa_operation_unref(operation);
|
||||
pa_threaded_mainloop_unlock(mainLoop);
|
||||
|
||||
if (!streamCmdStatus) {
|
||||
MEDIA_ERR_LOG("Stream Stop Failed");
|
||||
return AUDIO_CLIENT_ERR;
|
||||
} else {
|
||||
MEDIA_INFO_LOG("Stream Stopped Successfully");
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t AudioServiceClient::FlushStream()
|
||||
@ -1143,6 +1210,13 @@ int32_t AudioServiceClient::ReadStream(StreamBuffer &stream, bool isBlocking)
|
||||
int32_t AudioServiceClient::ReleaseStream()
|
||||
{
|
||||
ResetPAAudioClient();
|
||||
state_ = RELEASED;
|
||||
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(state_);
|
||||
}
|
||||
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1165,7 +1239,6 @@ int32_t AudioServiceClient::GetMinimumBufferSize(size_t &minBufferSize)
|
||||
minBufferSize = (size_t)bufferAttr->fragsize;
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("buffer size: %zu", minBufferSize);
|
||||
return AUDIO_CLIENT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1558,5 +1631,19 @@ AudioRendererRate AudioServiceClient::GetStreamRenderRate()
|
||||
{
|
||||
return renderRate;
|
||||
}
|
||||
|
||||
void AudioServiceClient::SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> &callback)
|
||||
{
|
||||
streamCallback_ = callback;
|
||||
|
||||
if (state_ != PREPARED) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
|
||||
if (streamCb != nullptr) {
|
||||
streamCb->OnStateChange(state_);
|
||||
}
|
||||
}
|
||||
} // namespace AudioStandard
|
||||
} // namespace OHOS
|
||||
|
@ -455,5 +455,17 @@ AudioRendererRate AudioStream::GetRenderRate()
|
||||
{
|
||||
return GetStreamRenderRate();
|
||||
}
|
||||
|
||||
int32_t AudioStream::SetStreamCallback(const std::shared_ptr<AudioStreamCallback> &callback)
|
||||
{
|
||||
if (callback == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioStream::SetStreamCallback failed. callback == nullptr");
|
||||
return ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SaveStreamCallback(callback);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
} // namspace AudioStandard
|
||||
} // namespace OHOS
|
||||
|
@ -33,6 +33,32 @@ namespace AudioTestConstants {
|
||||
constexpr int32_t SUCCESS = 0;
|
||||
}
|
||||
|
||||
class AudioCapturerCallbackTestImpl : public AudioCapturerCallback {
|
||||
public:
|
||||
void OnStateChange(const CapturerState state) override
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl:: OnStateChange");
|
||||
|
||||
switch (state) {
|
||||
case CAPTURER_PREPARED:
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_PREPARED");
|
||||
break;
|
||||
case CAPTURER_RUNNING:
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RUNNING");
|
||||
break;
|
||||
case CAPTURER_STOPPED:
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_STOPPED");
|
||||
break;
|
||||
case CAPTURER_RELEASED:
|
||||
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RELEASED");
|
||||
break;
|
||||
default:
|
||||
MEDIA_ERR_LOG("AudioCapturerCallbackTestImpl: OnStateChange NOT A VALID state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AudioCapturerTest {
|
||||
public:
|
||||
void CheckSupportedParams() const
|
||||
@ -157,6 +183,14 @@ public:
|
||||
|
||||
unique_ptr<AudioCapturer> audioCapturer = AudioCapturer::Create(capturerOptions);
|
||||
|
||||
int32_t ret = 0;
|
||||
shared_ptr<AudioCapturerCallback> cb1 = make_shared<AudioCapturerCallbackTestImpl>();
|
||||
ret = audioCapturer->SetCapturerCallback(cb1);
|
||||
if (ret) {
|
||||
MEDIA_ERR_LOG("AudioCapturerTest: SetCapturerCallback failed %{public}d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckSupportedParams();
|
||||
|
||||
if (!InitCapture(audioCapturer)) {
|
||||
|
@ -21,8 +21,30 @@ using namespace std;
|
||||
|
||||
namespace OHOS {
|
||||
namespace AudioStandard {
|
||||
namespace AudioTestConstants {
|
||||
constexpr int32_t SUCCESS = 0;
|
||||
void AudioInterruptTest::OnStateChange(const RendererState state)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest:: OnStateChange");
|
||||
|
||||
switch (state) {
|
||||
case RENDERER_PREPARED:
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_PREPARED");
|
||||
break;
|
||||
case RENDERER_RUNNING:
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_RUNNING");
|
||||
break;
|
||||
case RENDERER_STOPPED:
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_STOPPED");
|
||||
break;
|
||||
case RENDERER_PAUSED:
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_PAUSED");
|
||||
break;
|
||||
case RENDERER_RELEASED:
|
||||
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_RELEASED");
|
||||
break;
|
||||
default:
|
||||
MEDIA_ERR_LOG("AudioInterruptTest: OnStateChange NOT A VALID state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInterruptTest::OnInterrupt(const InterruptEvent &interruptEvent)
|
||||
@ -158,7 +180,7 @@ bool AudioInterruptTest::StartRender()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioInterruptTest::InitRender() const
|
||||
bool AudioInterruptTest::InitRender()
|
||||
{
|
||||
wav_hdr wavHeader;
|
||||
size_t headerSize = sizeof(wav_hdr);
|
||||
@ -168,17 +190,18 @@ bool AudioInterruptTest::InitRender() const
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioRendererParams rendererParams;
|
||||
rendererParams.sampleFormat = static_cast<AudioSampleFormat>(wavHeader.bitsPerSample);
|
||||
rendererParams.sampleRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
|
||||
rendererParams.channelCount = static_cast<AudioChannel>(wavHeader.NumOfChan);
|
||||
rendererParams.encodingType = static_cast<AudioEncodingType>(ENCODING_PCM);
|
||||
AudioRendererOptions rendererOptions = {};
|
||||
rendererOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
|
||||
rendererOptions.streamInfo.samplingRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
|
||||
rendererOptions.streamInfo.format = static_cast<AudioSampleFormat>(wavHeader.bitsPerSample);
|
||||
rendererOptions.streamInfo.channels = static_cast<AudioChannel>(wavHeader.NumOfChan);
|
||||
rendererOptions.rendererInfo.contentType = contentType_;
|
||||
rendererOptions.rendererInfo.streamUsage = streamUsage_;
|
||||
rendererOptions.rendererInfo.rendererFlags = 0;
|
||||
|
||||
if (audioRenderer_->SetParams(rendererParams) != AudioTestConstants::SUCCESS) {
|
||||
MEDIA_ERR_LOG("AudioInterruptTest: Set audio renderer parameters failed");
|
||||
if (!audioRenderer_->Release()) {
|
||||
MEDIA_ERR_LOG("AudioInterruptTest: Release failed");
|
||||
}
|
||||
audioRenderer_ = AudioRenderer::Create(rendererOptions);
|
||||
if (audioRenderer_== nullptr) {
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: Renderer create failed");
|
||||
return false;
|
||||
}
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: Playback renderer created");
|
||||
@ -186,10 +209,9 @@ bool AudioInterruptTest::InitRender() const
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t AudioInterruptTest::TestPlayback(const AudioStreamType &streamType)
|
||||
int32_t AudioInterruptTest::TestPlayback()
|
||||
{
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: TestPlayback start ");
|
||||
audioRenderer_ = AudioRenderer::Create(streamType);
|
||||
if (!InitRender()) {
|
||||
fclose(wavFile_);
|
||||
return -1;
|
||||
@ -232,6 +254,12 @@ int32_t AudioInterruptTest::TestPlayback(const AudioStreamType &streamType)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioInterruptTest::saveStreamInfo(ContentType contentType, StreamUsage streamUsage)
|
||||
{
|
||||
contentType_ = contentType;
|
||||
streamUsage_ = streamUsage;
|
||||
}
|
||||
} // AudioStandard
|
||||
} // OHOS
|
||||
|
||||
@ -243,12 +271,18 @@ int main(int argc, char *argv[])
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: Render test in");
|
||||
constexpr int32_t minNumOfArgs = 2;
|
||||
constexpr int32_t argIndexTwo = 2;
|
||||
constexpr int32_t argIndexThree = 3;
|
||||
|
||||
if ((argv == nullptr) || (argc < minNumOfArgs)) {
|
||||
if (argv == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioInterruptTest: argv is null");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc < minNumOfArgs || argc == minNumOfArgs + 1) {
|
||||
MEDIA_ERR_LOG("AudioInterruptTest: incorrect argc. Enter either 2 or 4 args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: argc=%d", argc);
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: argv[1]=%{public}s", argv[1]);
|
||||
|
||||
@ -261,10 +295,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
MEDIA_INFO_LOG("AudioInterruptTest: path = %{public}s", path);
|
||||
|
||||
AudioStreamType streamType = AudioStreamType::STREAM_MUSIC;
|
||||
if (argc > minNumOfArgs)
|
||||
streamType = static_cast<AudioStreamType>(strtol(argv[argIndexTwo], NULL, numBase));
|
||||
|
||||
auto audioInterruptTest = std::make_shared<AudioInterruptTest>();
|
||||
|
||||
audioInterruptTest->wavFile_ = fopen(path, "rb");
|
||||
@ -273,7 +303,13 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ret = audioInterruptTest->TestPlayback(streamType);
|
||||
if (argc > minNumOfArgs + 1) { // argc = 4
|
||||
ContentType contentType = static_cast<ContentType>(strtol(argv[argIndexTwo], NULL, numBase));
|
||||
StreamUsage streamUsage = static_cast<StreamUsage>(strtol(argv[argIndexThree], NULL, numBase));
|
||||
audioInterruptTest->saveStreamInfo(contentType, streamUsage);
|
||||
}
|
||||
|
||||
int32_t ret = audioInterruptTest->TestPlayback();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -30,12 +30,13 @@ public:
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
int32_t TestPlayback(const AudioStreamType &streamType);
|
||||
int32_t TestPlayback();
|
||||
void OnInterrupt(const InterruptEvent &interruptEvent) override;
|
||||
void OnStateChange(const RendererState state) override;
|
||||
void saveStreamInfo(ContentType contentType, StreamUsage streamUsage);
|
||||
FILE *wavFile_ = nullptr;
|
||||
|
||||
private:
|
||||
bool InitRender() const;
|
||||
bool InitRender();
|
||||
bool StartRender();
|
||||
bool GetBufferLen(size_t &bufferLen) const;
|
||||
void WriteBuffer();
|
||||
@ -46,6 +47,8 @@ private:
|
||||
bool isRenderStopped_ = false;
|
||||
bool isRenderingCompleted_ = false;
|
||||
std::unique_ptr<std::thread> writeThread_ = nullptr;
|
||||
ContentType contentType_ = ContentType::CONTENT_TYPE_MUSIC;
|
||||
StreamUsage streamUsage_ = StreamUsage::STREAM_USAGE_MEDIA;
|
||||
};
|
||||
} // AudioStandard
|
||||
} // OHOS
|
||||
|
@ -22,9 +22,10 @@ using namespace std;
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::AudioStandard;
|
||||
|
||||
namespace AudioTestConstants {
|
||||
namespace {
|
||||
constexpr int32_t ARGS_INDEX_THREE = 3;
|
||||
constexpr int32_t ARGS_INDEX_TWO = 2;
|
||||
constexpr int32_t ARGS_COUNT_TWO = 2;
|
||||
constexpr int32_t ARGS_COUNT_THREE = 3;
|
||||
constexpr int32_t SUCCESS = 0;
|
||||
constexpr int32_t STOP_BUFFER_POSITION = 700000;
|
||||
@ -34,6 +35,36 @@ namespace AudioTestConstants {
|
||||
constexpr float TRACK_VOLUME = 0.2f;
|
||||
}
|
||||
|
||||
class AudioRendererCallbackTestImpl : public AudioRendererCallback {
|
||||
public:
|
||||
void OnInterrupt(const InterruptEvent &interruptEvent) override {}
|
||||
void OnStateChange(const RendererState state) override
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl:: OnStateChange");
|
||||
|
||||
switch (state) {
|
||||
case RENDERER_PREPARED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PREPARED");
|
||||
break;
|
||||
case RENDERER_RUNNING:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RUNNING");
|
||||
break;
|
||||
case RENDERER_STOPPED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_STOPPED");
|
||||
break;
|
||||
case RENDERER_PAUSED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PAUSED");
|
||||
break;
|
||||
case RENDERER_RELEASED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RELEASED");
|
||||
break;
|
||||
default:
|
||||
MEDIA_ERR_LOG("AudioRendererCallbackTestImpl: OnStateChange NOT A VALID state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AudioRendererTest {
|
||||
public:
|
||||
void CheckSupportedParams() const
|
||||
@ -64,6 +95,29 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void GetRendererStreamInfo(const unique_ptr<AudioRenderer> &audioRenderer) const
|
||||
{
|
||||
MEDIA_INFO_LOG("AudioRendererTest: GetRendererInfo:");
|
||||
AudioRendererInfo rendererInfo;
|
||||
if (audioRenderer->GetRendererInfo(rendererInfo) == SUCCESS) {
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get ContentType: %{public}d", rendererInfo.contentType);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get StreamUsage: %{public}d", rendererInfo.streamUsage);
|
||||
} else {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: GetStreamInfo failed");
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("AudioRendererTest: GetStreamInfo:");
|
||||
AudioStreamInfo streamInfo;
|
||||
if (audioRenderer->GetStreamInfo(streamInfo) == SUCCESS) {
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get AudioSamplingRate: %{public}d", streamInfo.samplingRate);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get AudioEncodingType: %{public}d", streamInfo.encoding);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get AudioSampleFormat: %{public}d", streamInfo.format);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get AudioChannel: %{public}d", streamInfo.channels);
|
||||
} else {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: GetStreamInfo failed");
|
||||
}
|
||||
}
|
||||
|
||||
bool InitRender(const unique_ptr<AudioRenderer> &audioRenderer) const
|
||||
{
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Starting renderer");
|
||||
@ -76,20 +130,10 @@ public:
|
||||
}
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Playback started");
|
||||
|
||||
if (audioRenderer->SetVolume(AudioTestConstants::TRACK_VOLUME) == AudioTestConstants::SUCCESS) {
|
||||
if (audioRenderer->SetVolume(TRACK_VOLUME) == SUCCESS) {
|
||||
MEDIA_INFO_LOG("AudioRendererTest: volume set to: %{public}f", audioRenderer->GetVolume());
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get Audio parameters:");
|
||||
AudioRendererParams paRendererParams;
|
||||
if (audioRenderer->GetParams(paRendererParams) == AudioTestConstants::SUCCESS) {
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get Audio format: %{public}d", paRendererParams.sampleFormat);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get Audio sampling rate: %{public}d", paRendererParams.sampleRate);
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Get Audio channels: %{public}d", paRendererParams.channelCount);
|
||||
} else {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: Get Audio parameters failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -97,20 +141,20 @@ public:
|
||||
FILE &wavFile) const
|
||||
{
|
||||
uint64_t currFilePos = ftell(&wavFile);
|
||||
if (!stopTested && (currFilePos > AudioTestConstants::STOP_BUFFER_POSITION) && audioRenderer->Stop()) {
|
||||
if (!stopTested && (currFilePos > STOP_BUFFER_POSITION) && audioRenderer->Stop()) {
|
||||
stopTested = true;
|
||||
sleep(AudioTestConstants::STOP_RENDER_TIME_SECONDS);
|
||||
sleep(STOP_RENDER_TIME_SECONDS);
|
||||
MEDIA_INFO_LOG("Audio render resume");
|
||||
if (!audioRenderer->Start()) {
|
||||
MEDIA_ERR_LOG("resume stream failed");
|
||||
return false;
|
||||
}
|
||||
} else if (!pauseTested && (currFilePos > AudioTestConstants::PAUSE_BUFFER_POSITION)
|
||||
} else if (!pauseTested && (currFilePos > PAUSE_BUFFER_POSITION)
|
||||
&& audioRenderer->Pause()) {
|
||||
pauseTested = true;
|
||||
sleep(AudioTestConstants::PAUSE_RENDER_TIME_SECONDS);
|
||||
sleep(PAUSE_RENDER_TIME_SECONDS);
|
||||
MEDIA_INFO_LOG("Audio render resume");
|
||||
if (audioRenderer->SetVolume(1.0) == AudioTestConstants::SUCCESS) {
|
||||
if (audioRenderer->SetVolume(1.0) == SUCCESS) {
|
||||
MEDIA_INFO_LOG("AudioRendererTest: after resume volume set to: %{public}f",
|
||||
audioRenderer->GetVolume());
|
||||
}
|
||||
@ -219,9 +263,9 @@ public:
|
||||
ContentType contentType = ContentType::CONTENT_TYPE_MUSIC;
|
||||
StreamUsage streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
|
||||
|
||||
if (argc > AudioTestConstants::ARGS_COUNT_THREE) {
|
||||
contentType = static_cast<ContentType>(strtol(argv[AudioTestConstants::ARGS_INDEX_TWO], NULL, numBase));
|
||||
streamUsage = static_cast<StreamUsage>(strtol(argv[AudioTestConstants::ARGS_INDEX_THREE], NULL, numBase));
|
||||
if (argc > ARGS_COUNT_THREE) {
|
||||
contentType = static_cast<ContentType>(strtol(argv[ARGS_INDEX_TWO], NULL, numBase));
|
||||
streamUsage = static_cast<StreamUsage>(strtol(argv[ARGS_INDEX_THREE], NULL, numBase));
|
||||
}
|
||||
|
||||
AudioRendererOptions rendererOptions = {};
|
||||
@ -235,6 +279,21 @@ public:
|
||||
|
||||
unique_ptr<AudioRenderer> audioRenderer = AudioRenderer::Create(rendererOptions);
|
||||
|
||||
if (audioRenderer == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: Create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t ret = 0;
|
||||
shared_ptr<AudioRendererCallback> cb1 = make_shared<AudioRendererCallbackTestImpl>();
|
||||
ret = audioRenderer->SetRendererCallback(cb1);
|
||||
if (ret) {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: SetRendererCallback failed %{public}d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
GetRendererStreamInfo(audioRenderer);
|
||||
|
||||
CheckSupportedParams();
|
||||
|
||||
if (!InitRender(audioRenderer)) {
|
||||
@ -268,15 +327,18 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
MEDIA_INFO_LOG("AudioRendererTest: Render test in");
|
||||
|
||||
if ((argv == nullptr) || (argc < AudioTestConstants::ARGS_COUNT_THREE)) {
|
||||
if (argv == nullptr) {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: argv is null");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc < ARGS_COUNT_TWO || argc == ARGS_COUNT_THREE) {
|
||||
MEDIA_ERR_LOG("AudioRendererTest: incorrect argc. Enter either 2 or 4 args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("AudioRendererTest: argc=%{public}d", argc);
|
||||
MEDIA_INFO_LOG("file path argv[1]=%{public}s", argv[1]);
|
||||
MEDIA_INFO_LOG("content type argv[2]=%{public}s", argv[AudioTestConstants::ARGS_INDEX_TWO]);
|
||||
MEDIA_INFO_LOG("stream usage argv[3]=%{public}s", argv[AudioTestConstants::ARGS_INDEX_THREE]);
|
||||
|
||||
AudioRendererTest testObj;
|
||||
bool ret = testObj.TestPlayback(argc, argv);
|
||||
|
@ -34,6 +34,32 @@ namespace {
|
||||
constexpr int32_t NUM_BASE = 10;
|
||||
}
|
||||
|
||||
void AudioRendererCallbackTestImpl::OnStateChange(const RendererState state)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl:: OnStateChange");
|
||||
|
||||
switch (state) {
|
||||
case RENDERER_PREPARED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PREPARED");
|
||||
break;
|
||||
case RENDERER_RUNNING:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RUNNING");
|
||||
break;
|
||||
case RENDERER_STOPPED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_STOPPED");
|
||||
break;
|
||||
case RENDERER_PAUSED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PAUSED");
|
||||
break;
|
||||
case RENDERER_RELEASED:
|
||||
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RELEASED");
|
||||
break;
|
||||
default:
|
||||
MEDIA_ERR_LOG("AudioRendererCallbackTestImpl: OnStateChange NOT A VALID state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRendererCallbackTestImpl::OnInterrupt(const InterruptEvent &interruptEvent)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("InterruptMultiRendererTest: OnInterrupt");
|
||||
|
@ -23,6 +23,7 @@ namespace AudioStandard {
|
||||
class AudioRendererCallbackTestImpl : public AudioRendererCallback {
|
||||
public:
|
||||
void OnInterrupt(const InterruptEvent &interruptEvent) override;
|
||||
void OnStateChange(const RendererState state) override;
|
||||
bool isRendererPaused_ = false;
|
||||
bool isStopInProgress_ = false;
|
||||
bool isRendererStopped_ = false;
|
||||
|
@ -23,6 +23,7 @@ namespace AudioStandard {
|
||||
class AudioRendererCallbackTest : public AudioRendererCallback {
|
||||
public:
|
||||
void OnInterrupt(const InterruptEvent &interruptEvent) override;
|
||||
void OnStateChange(const RendererState state) override {}
|
||||
};
|
||||
|
||||
class AudioRendererUnitTest : public testing::Test {
|
||||
|
Loading…
Reference in New Issue
Block a user