doubao_chat/lib/net/libduer-device/modules/dcs/lightduer_dcs_local.c

458 lines
14 KiB
C

/**
* Copyright (2017) Baidu Inc. All rights reserved.
*
* 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.
*/
/**
* File: lightduer_dcs_local.c
* Auth: Gang Chen (chengang12@baidu.com)
* Desc: Provide some functions for dcs module local.
*/
#include "lightduer_dcs_local.h"
#include <stdlib.h>
#include "lightduer_log.h"
#include "lightduer_lib.h"
#include "lightduer_memory.h"
#include "lightduer_ds_log_dcs.h"
#include "lightduer_mutex.h"
#include "lightduer_random.h"
#include "lightduer_voice.h"
#include "lightduer_connagent.h"
#include "lightduer_engine.h"
#include "lightduer_timestamp.h"
#define RANDOM_NUM_COUNT 3
#define RANDOM_NUM_LEN 8
#define RANDOM_PART_LEN (RANDOM_NUM_COUNT * RANDOM_NUM_LEN)
// resouce path
const char *DCS_DUER_DIRECTIVE_PATH = "duer_directive";
const char *DCS_DUER_PRIVATE_PATH = "duer_private";
const char *DCS_IOTCLOUD_DIRECTIVE_PATH = "duer_iotcloud_directive";
const char *DCS_IOTCLOUD_EVENT_PATH = "duer_iotcloud_event";
const char *DCS_DUER_DLP_PATH = "duer_dlp";
// namespace
const char *DCS_AUDIO_PLAYER_NAMESPACE = "ai.dueros.device_interface.audio_player";
const char *DCS_VOICE_OUTPUT_NAMESPACE = "ai.dueros.device_interface.voice_output";
const char *DCS_VOICE_INPUT_NAMESPACE = "ai.dueros.device_interface.voice_input";
const char *DCS_SCREEN_NAMESPACE = "ai.dueros.device_interface.screen";
const char *DCS_SCREEN_EXTENDED_CARD_NAMESPACE = "ai.dueros.device_interface.screen_extended_card";
const char *DCS_IOT_CLOUD_SYSTEM_NAMESPACE = "ai.dueros.device_interface.iot_cloud.system";
const char *DCS_PLAYBACK_CONTROL_NAMESPACE = "ai.dueros.device_interface.playback_controller";
const char *DCS_RECOMMEND_NAMESPACE = "ai.dueros.device_interface.extensions.recommend";
const char *DCS_PRIVATE_NAMESPACE = "ai.dueros.private.protocol";
const char *DCS_PUSH_SERVICE_NAMESPACE = "ai.dueros.device_interface.push_service";
// message keys
const char *DCS_DIRECTIVE_KEY = "directive";
const char *DCS_CLIENT_CONTEXT_KEY = "clientContext";
const char *DCS_EVENT_KEY = "event";
const char *DCS_HEADER_KEY = "header";
const char *DCS_PAYLOAD_KEY = "payload";
// header keys
const char *DCS_NAMESPACE_KEY = "namespace";
const char *DCS_NAME_KEY = "name";
const char *DCS_MESSAGE_ID_KEY = "messageId";
const char *DCS_DIALOG_REQUEST_ID_KEY = "dialogRequestId";
// payload keys
const char *DCS_TOKEN_KEY = "token";
const char *DCS_TYPE_KEY = "type";
const char *DCS_CODE_KEY = "code";
const char *DCS_VOLUME_KEY = "volume";
const char *DCS_URL_KEY = "url";
const char *DCS_ACTIVE_ALERTS_KEY = "activeAlerts";
const char *DCS_TARGET_KEY = "target";
const char *DCS_SCHEDULED_TIME_KEY = "scheduled_time";
const char *DCS_PLAYER_ACTIVITY_KEY = "playerActivity";
const char *DCS_ALL_ALERTS_KEY = "allAlerts";
const char *DCS_ERROR_KEY = "error";
const char *DCS_MUTE_KEY = "mute";
const char *DCS_INITIATOR_KEY = "initiator";
const char *DCS_AUDIO_ITEM_KEY = "audioItem";
const char *DCS_CLEAR_BEHAVIOR_KEY = "clearBehavior";
const char *DCS_PLAY_BEHAVIOR_KEY = "playBehavior";
const char *DCS_INACTIVE_TIME_IN_SECONDS_KEY = "inactiveTimeInSeconds";
const char *DCS_OFFSET_IN_MILLISECONDS_KEY = "offsetInMilliseconds";
const char *DCS_TIMEOUT_IN_MILLISECONDS_KEY = "timeoutInMilliseconds";
const char *DCS_METADATA_KEY = "metadata";
const char *DCS_TEXT_KEY = "text";
const char *DCS_CONNECTION_SWITCH_KEY = "connectionSwitch";
const char *DCS_DESCRIPTION_KEY = "description";
const char *DCS_BLUETOOTH_KEY = "bluetooth";
const char *DCS_MUTED_KEY = "muted";
const char *DCS_UNPARSED_DIRECTIVE_KEY = "unparsedDirective";
const char *DCS_FORMAT_KEY = "format";
const char *DCS_MESSAGE_KEY = "message";
const char *DCS_QUERY_KEY = "query";
const char *DCS_TIME_OF_RECOMMEND = "timeOfRecommendation";
const char *DCS_STUTTER_DURATION = "stutterDurationInMilliseconds";
const char *DCS_PREVIOUS_DIALOG_ID_KEY = "previousDialogRequestId";
const char *DCS_ACTIVE_DIALOG_ID_KEY = "activeDialogRequestId";
// directive name
const char *DCS_SPEAK_NAME = "Speak";
const char *DCS_PLAY_NAME = "Play"; // Audio
const char *DCS_STOP_NAME = "Stop"; // Audio
const char *DCS_CLEAR_QUEUE_NAME = "ClearQueue"; // Audio
const char *DCS_LISTEN_NAME = "Listen";
const char *DCS_GET_STATUS_NAME = "GetStatus";
const char *DCS_STOP_SPEAK_NAME = "StopSpeak";
const char *DCS_SET_BLUETOOTH_NAME = "SetBluetooth";
const char *DCS_RENDER_CARD_NAME = "RenderCard";
const char *DCS_SET_ALERT_NAME = "SetAlert";
const char *DCS_STOP_LISTEN_NAME = "StopListen";
const char *DCS_SET_BLUETOOTH_CONNECTION_NAME = "SetBluetoothConnection";
const char *DCS_SET_MUTE_NAME = "SetMute";
const char *DCS_DELETE_ALERT_NAME = "DeleteAlert";
const char *DCS_RENDER_VOICE_INPUT_TEXT_NAME = "RenderVoiceInputText";
const char *DCS_SET_VOLUME_NAME = "SetVolume";
const char *DCS_ADJUST_VOLUME_NAME = "AdjustVolume";
const char *DCS_TEXT_INPUT_NAME = "TextInput";
const char *DCS_RENDER_WEATHER = "RenderWeather";
const char *DCS_RENDER_PLAYER_INFO = "RenderPlayerInfo";
extern const char *DCS_RENDER_AUDIO_LIST = "RenderAudioList";
extern const char *DCS_RENDER_ALBUM_LIST = "RenderAlbumList";
const char *DCS_SET_ACTIVE_DIALOG = "SetActiveDialog";
const char *DCS_REQUIRE_PUSH_ACK = "RequirePushAck";
// internal directive.
const char *DCS_DIALOGUE_FINISHED_NAME = "DialogueFinished";
const char *DCS_THROW_EXCEPTION_NAME = "ThrowException";
const char *DCS_RESET_USER_INACTIVITY_NAME = "ResetUserInactivity";
const char *DCS_NOP_NAME = "Nop";
const char *DCS_IOT_CLOUD_CONTEXT = "Context";
// event name
const char *DCS_SYNCHRONIZE_STATE_NAME = "SynchronizeState";
const char *DCS_EXCEPTION_ENCOUNTERED_NAME = "ExceptionEncountered";
const char *DCS_VOLUME_STATE_NAME = "Volume";
const char *DCS_LISTEN_STARTED_NAME = "ListenStarted";
const char *DCS_SPEECH_STARTED_NAME = "SpeechStarted";
const char *DCS_ALERTS_STATE_NAME = "AlertsState";
const char *DCS_LISTEN_TIMED_OUT_NAME = "ListenTimedOut";
const char *DCS_EXITED_NAME = "Exited";
const char *DCS_PLAYBACK_STATE_NAME = "PlaybackState";
const char *DCS_SPEECH_FINISHED_NAME = "SpeechFinished";
const char *DCS_VOLUME_CHANGED_NAME = "VolumeChanged";
const char *DCS_MUTE_CHANGED_NAME = "MuteChanged";
const char *DCS_SPEECH_STATE_NAME = "SpeechState";
const char *DCS_LINK_CLICKED_NAME = "LinkClicked";
const char *DCS_RECOMMEND_NAME = "RecommendationRequested";
const char *DCS_PUSH_ACK_NAME = "PushAck";
// internal exception type
const char *DCS_UNEXPECTED_INFORMATION_RECEIVED_TYPE = "UNEXPECTED_INFORMATION_RECEIVED";
const char *DCS_INTERNAL_ERROR_TYPE = "INTERNAL_ERROR";
const char *DCS_UNSUPPORTED_OPERATION_TYPE = "UNSUPPORTED_OPERATION";
static duer_mutex_t s_dcs_local_lock;
static char *s_dialog_req_id;
static int s_dialog_id_buf_len;
static int s_msg_id_buf_len;
static char *s_msg_id;
static duer_bool s_is_dialog_id_exist;
static duer_dcs_dialog_request_t s_dialog_request_type;
static dcs_event_hook s_dcs_hook_event_handler = NULL;
int duer_dcs_data_report_internal(baidu_json *data, duer_bool is_transparent)
{
int rs = DUER_OK;
if (!data) {
return DUER_ERR_INVALID_PARAMETER;
}
if (s_dcs_hook_event_handler) {
s_dcs_hook_event_handler(data);
}
if (!is_transparent) {
duer_add_translate_flag(data);
}
rs = duer_data_report(data);
return rs;
}
void duer_reg_dcs_event_hook_hdl_internal(dcs_event_hook cb)
{
if (!s_dcs_hook_event_handler) {
s_dcs_hook_event_handler = cb;
DUER_LOGI("dcs_event_hook_hdl initialized");
} else {
DUER_LOGI("dcs_event_hook_hdl has been initialized");
}
}
static const char *duer_create_random_id(char *buf, int len)
{
static int count = 0;
if (buf) {
DUER_SNPRINTF(buf, len, "%s%08x%08x%08x",
duer_engine_get_uuid(), duer_random(), duer_timestamp(), count++);
}
return buf;
}
duer_dcs_dialog_request_t duer_get_dialog_request_type(void)
{
return s_dialog_request_type;
}
const char *duer_create_request_id_internal(duer_dcs_dialog_request_t type)
{
duer_create_random_id(s_dialog_req_id, s_dialog_id_buf_len);
s_dialog_request_type = type;
duer_cancel_caching_directive_internal();
DUER_LOGI("Current dialog id: %s", s_dialog_req_id);
s_is_dialog_id_exist = DUER_TRUE;
return s_dialog_req_id;
}
duer_status_t duer_set_dialog_id_internal(const char *dialog_id)
{
int len = DUER_STRLEN(dialog_id) + 1;
void *new_buf = NULL;
if (len > s_dialog_id_buf_len) {
new_buf = DUER_MALLOC(len);
if (!new_buf) {
return DUER_ERR_MEMORY_OVERFLOW;
}
if (s_dialog_req_id) {
DUER_FREE(s_dialog_req_id);
}
s_dialog_req_id = new_buf;
s_dialog_id_buf_len = len;
}
DUER_STRNCPY(s_dialog_req_id, dialog_id, s_dialog_id_buf_len);
s_is_dialog_id_exist = DUER_TRUE;
duer_cancel_caching_directive_internal();
return DUER_OK;
}
const char *duer_get_request_id_internal(void)
{
if (!s_is_dialog_id_exist) {
return duer_create_request_id_internal(DCS_DIALOG_NONE);
}
return s_dialog_req_id;
}
const char *duer_generate_msg_id_internal()
{
return duer_create_random_id(s_msg_id, s_msg_id_buf_len);
}
char *duer_strdup_internal(const char *str)
{
int len = 0;
char *dest = NULL;
if (!str) {
return NULL;
}
len = DUER_STRLEN(str);
dest = DUER_MALLOC(len + 1);
if (!dest) {
DUER_DS_LOG_REPORT_DCS_MEMORY_ERROR();
return NULL;
}
DUER_SNPRINTF(dest, len + 1, "%s", str);
return dest;
}
void duer_play_channel_control_internal(duer_dcs_channel_switch_event_t event)
{
switch (event) {
case DCS_RECORD_STARTED:
duer_speech_on_stop_internal();
if (duer_audio_is_playing_internal()) {
duer_pause_audio_internal(DUER_TRUE);
}
if (duer_local_player_is_playing_internal()) {
duer_pause_local_player_internal();
}
break;
case DCS_SPEECH_NEED_PLAY:
if (duer_audio_is_playing_internal()) {
duer_pause_audio_internal(DUER_TRUE);
} else if (duer_is_recording_internal()) {
duer_listen_stop_internal();
} else {
// do nothing
}
if (duer_local_player_is_playing_internal()) {
duer_pause_local_player_internal();
}
break;
case DCS_SPEECH_FINISHED:
if (duer_is_multiple_round_dialogue()) {
duer_open_mic_internal();
} else if (duer_audio_is_paused_internal() && !duer_wait_dialog_finished_internal()) {
duer_resume_audio_internal();
} else if (duer_local_player_is_paused_internal()
&& !duer_wait_dialog_finished_internal()) {
duer_resume_local_player_internal();
} else {
// do nothing
}
break;
case DCS_AUDIO_NEED_PLAY:
if (duer_local_player_is_paused_internal() || duer_local_player_is_playing_internal()) {
duer_stop_local_player_internal();
}
if (duer_speech_need_play_internal() || duer_is_recording_internal()) {
duer_pause_audio_internal(DUER_FALSE);
} else {
duer_start_audio_play_internal();
}
break;
case DCS_DIALOG_FINISHED:
if (duer_speech_need_play_internal()
|| duer_is_recording_internal()
|| duer_is_multiple_round_dialogue()) {
break;
}
if (duer_audio_is_paused_internal()) {
duer_resume_audio_internal();
} else if (duer_local_player_is_paused_internal()) {
duer_resume_local_player_internal();
} else {
// do nothing
}
break;
case DCS_AUDIO_FINISHED:
break;
case DCS_NEED_OPEN_MIC:
if (duer_speech_need_play_internal()) {
break;
}
if (duer_audio_is_playing_internal()) {
duer_pause_audio_internal(DUER_TRUE);
}
if (duer_local_player_is_playing_internal()) {
duer_pause_local_player_internal();
}
duer_open_mic_internal();
break;
case DCS_AUDIO_STOPPED:
break;
case DCS_ALERT_STARTED:
if (duer_audio_is_playing_internal()) {
duer_pause_audio_internal(DUER_TRUE);
}
if (duer_local_player_is_playing_internal()) {
duer_pause_local_player_internal();
}
break;
case DCS_ALERT_FINISHED:
if (duer_audio_is_paused_internal()) {
duer_resume_audio_internal();
} else if (duer_local_player_is_paused_internal()) {
duer_resume_local_player_internal();
} else {
// do nothing
}
break;
default:
break;
}
}
duer_status_t duer_dcs_critical_enter_internal()
{
return duer_mutex_lock(s_dcs_local_lock);
}
duer_status_t duer_dcs_critical_exit_internal()
{
return duer_mutex_unlock(s_dcs_local_lock);
}
void duer_dcs_local_init_internal(void)
{
const char *uuid = NULL;
int len = 0;
if (!s_dcs_local_lock) {
s_dcs_local_lock = duer_mutex_create();
if (!s_dcs_local_lock) {
DUER_LOGE("Failed to create s_dcs_local_lock");
}
}
uuid = duer_engine_get_uuid();
if (uuid) {
len = DUER_STRLEN(uuid);
s_dialog_id_buf_len = len + RANDOM_PART_LEN + 1;
s_msg_id_buf_len = s_dialog_id_buf_len;
if (!s_dialog_req_id) {
s_dialog_req_id = DUER_MALLOC(s_dialog_id_buf_len);
if (!s_dialog_req_id) {
DUER_LOGE("Failed malloc s_dialog_id");
}
}
if (!s_msg_id) {
s_msg_id = DUER_MALLOC(s_msg_id_buf_len);
if (!s_msg_id) {
DUER_LOGE("Failed malloc s_msg_id");
}
}
} else {
DUER_LOGE("Failed to get uuid");
}
}
void duer_dcs_local_uninitialize_internal(void)
{
s_dialog_id_buf_len = 0;
s_msg_id_buf_len = 0;
if (s_dialog_req_id) {
DUER_FREE(s_dialog_req_id);
s_dialog_req_id = NULL;
}
if (s_msg_id) {
DUER_FREE(s_msg_id);
s_msg_id = NULL;
}
if (s_dcs_local_lock) {
duer_mutex_destroy(s_dcs_local_lock);
s_dcs_local_lock = NULL;
}
}