static const char *g_current_lang = "en_US";
static int g_local_port_id = -1;
-static char g_current_maclient_appid[MAX_APPID_LEN] = {"com.samsung.bixby-voice"};
-static ma_client_s *g_current_maclient = NULL;
-/* The following variable would not be needed when ma_request_speech_data() gets implemented */
-static char g_launching_maclient_appid[MAX_APPID_LEN] = {""};
+#define MAX_MACLIENT_INFO_NUM 16
+#define MAX_WAKEUP_WORD_LEN 255
+typedef struct {
+ Eina_Bool used;
+ const char wakeup_word[MAX_WAKEUP_WORD_LEN];
+ const char appid[MAX_APPID_LEN];
+} ma_client_info;
+
+static ma_client_info g_maclient_info[MAX_MACLIENT_INFO_NUM] = {
+ {EINA_TRUE, {"hi bixby"}, {"com.samsung.bixby-voice"}},
+ {EINA_TRUE, {"alexa"}, {"com.samsung.alexa-voice"}},
+ {EINA_TRUE, {"hi google"}, {"com.samsung.google-voice"}},
+};
+
+typedef struct {
+ int pid;
+ char appid[MAX_APPID_LEN];
+} ma_client_s;
+
+static int g_current_maclient_info = 0;
+static const char *g_launching_maclient_appid = NULL;
/* client list */
static GSList* g_client_list = NULL;
-int mas_check_client_available()
-{
- if (g_current_maclient) {
- if (g_current_maclient->appid && 0 == strncmp(g_current_maclient_appid, g_current_maclient->appid, MAX_APPID_LEN)) {
- MAS_LOGD("MA client with appid %s currently seems to be available : %d",
- g_current_maclient_appid, g_current_maclient->pid);
- return 1;
- }
- }
- return 0;
-}
-
-int mas_launch_client()
-{
- app_control_h app_control;
- int ret = 0;
-
- MAS_LOGD("Current MA Client appid : %s", g_current_maclient_appid);
-
- ret = app_control_create(&app_control);
- if (APP_CONTROL_ERROR_NONE != ret) {
- MAS_LOGW("app_control_create returned %08x", ret);
- return -1;
- }
-
- ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
- if (APP_CONTROL_ERROR_NONE != ret) {
- MAS_LOGW("app_control_set_operation returned %08x", ret);
- app_control_destroy(app_control);
- return -1;
- }
-
- /* These extra data key/value should be defined somewhere in multi-assistant framework */
- ret = app_control_add_extra_data(app_control, "request_speech_data", "true");
- if (APP_CONTROL_ERROR_NONE != ret) {
- MAS_LOGW("app_control_add_extra_data returned %08x", ret);
- app_control_destroy(app_control);
- return -1;
- }
-
- ret = app_control_set_app_id(app_control, g_current_maclient_appid);
- if (APP_CONTROL_ERROR_NONE != ret) {
- MAS_LOGW("app_control_set_app_id returned %08x", ret);
- app_control_destroy(app_control);
- return -1;
- }
-
- ret = app_control_send_launch_request(app_control, NULL, NULL);
- if (APP_CONTROL_ERROR_NONE != ret) {
- MAS_LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, g_current_maclient_appid);
- }
- app_control_destroy (app_control);
-
- if (APP_CONTROL_ERROR_NONE == ret) {
- strncpy(g_launching_maclient_appid, g_current_maclient_appid, MAX_APPID_LEN);
- g_launching_maclient_appid[MAX_APPID_LEN - 1] = '\0';
- }
-
- return ret;
-}
-
int ma_client_create(ma_client_s info)
{
ma_client_s* data = NULL;
{
if (NULL == appid) {
MAS_LOGE("Input parameter is NULL"); //LCOV_EXCL_LINE
- return -1;// MA_ERROR_OPERATION_FAILED;
+ return NULL;
}
ma_client_s *data = NULL;
char appid[MAX_APPID_LEN] = {'\0',};
if (AUL_R_OK == aul_app_get_appid_bypid(pid, appid, sizeof(appid))) {
appid[MAX_APPID_LEN - 1] = '\0';
- if (strncmp(g_launching_maclient_appid, appid, MAX_APPID_LEN) == 0) {
- g_launching_maclient_appid[0] = '\0';
+ if (0 == strncmp(g_launching_maclient_appid, appid, MAX_APPID_LEN)) {
+ g_launching_maclient_appid = NULL;
mas_client_request_speech_data(pid);
}
}
new_client.appid[MAX_APPID_LEN - 1] = '\0';
ma_client_create(new_client);
- if (0 == strncmp(g_current_maclient_appid, appid, MAX_APPID_LEN)) {
- g_current_maclient = &new_client;
+ const char *current_maclient_appid = NULL;
+ if (g_current_maclient_info >= 0 && g_current_maclient_info < MAX_MACLIENT_INFO_NUM) {
+ current_maclient_appid = g_maclient_info[g_current_maclient_info].appid;
+ }
+
+ if (current_maclient_appid && 0 == strncmp(current_maclient_appid, appid, MAX_APPID_LEN)) {
MAS_LOGD("MA client with current maclient appid connected!");
/* Since the ma_request_speech_data() is not available, we will request speech data here.
Need to remove below code when ma_request_speech_data() get implemented.
*/
ecore_timer_add(3.0f, __request_speech_data_timer, (void*)(pid));
+ } else {
+ MAS_LOGD("MA client connected, but its appid does not match with current maclient");
}
+ } else {
+ MAS_LOGE("[ERROR] Fail to retrieve appid");
}
return 0;
char appid[MAX_APPID_LEN] = {'\0',};
if (AUL_R_OK == aul_app_get_appid_bypid(pid, appid, sizeof(appid))) {
appid[MAX_APPID_LEN - 1] = '\0';
+ const char *current_maclient_appid = NULL;
+ if (g_current_maclient_info >= 0 && g_current_maclient_info < MAX_MACLIENT_INFO_NUM) {
+ current_maclient_appid = g_maclient_info[g_current_maclient_info].appid;
+ }
- if (0 == strncmp(g_current_maclient_appid, appid, MAX_APPID_LEN)) {
+ if (current_maclient_appid && 0 == strncmp(current_maclient_appid, appid, MAX_APPID_LEN)) {
MAS_LOGD("appid %s matches with current MA Client, requesting speech data", appid);
ret = wakeup_service_request_speech_data();
if (0 != ret) {
return -1;
}
- if (0 != multi_assistant_service_plugin_set_wakeup_word("en_US", "hi bixby")) {
- MAS_LOGE("Fail to stt wakeup word");
- return -1;
- }
-
- if (0 != multi_assistant_service_plugin_set_wakeup_word("en_US", "alexa")) {
- MAS_LOGE("Fail to stt wakeup word");
- return -1;
- }
-
- if (0 != multi_assistant_service_plugin_set_wakeup_word("en_US", "hi google")) {
- MAS_LOGE("Fail to stt wakeup word");
- return -1;
+ for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
+ if (g_maclient_info[loop].used &&
+ strlen(g_maclient_info[loop].appid) > 0 &&
+ strlen(g_maclient_info[loop].wakeup_word) > 0) {
+ MAS_LOGD("Registering wakeup word %s for app %s",
+ g_maclient_info[loop].wakeup_word, g_maclient_info[loop].appid);
+ if (0 != multi_assistant_service_plugin_set_wakeup_word("en_US", g_maclient_info[loop].wakeup_word)) {
+ MAS_LOGE("Fail to stt wakeup word");
+ return -1;
+ }
+ }
}
if (0 != multi_assistant_service_plugin_set_callbacks()) {
}
}
+static const char* __get_client_appid_by_wakeup_word(const char *wakeup_word)
+{
+ int loop;
+ const char *appid = NULL;
+
+ if (NULL == wakeup_word) return NULL;
+
+ for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && appid == NULL; loop++) {
+ if (g_maclient_info[loop].used &&
+ strlen(g_maclient_info[loop].appid) > 0 &&
+ strlen(g_maclient_info[loop].wakeup_word) > 0) {
+ if (0 == strncmp(wakeup_word, g_maclient_info[loop].wakeup_word, MAX_WAKEUP_WORD_LEN)) {
+ appid = g_maclient_info[loop].appid;
+ }
+ }
+ }
+
+ /* Perform extended search, by eliminating blank characters */
+ if (NULL == appid) {
+ for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && appid == NULL; loop++) {
+ if (g_maclient_info[loop].used &&
+ strlen(g_maclient_info[loop].appid) > 0 &&
+ strlen(g_maclient_info[loop].wakeup_word) > 0) {
+ char comparand[MAX_WAKEUP_WORD_LEN];
+ int comparand_index = 0;
+ for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
+ if (' ' != g_maclient_info[loop].wakeup_word[index]) {
+ comparand[comparand_index++] = g_maclient_info[loop].wakeup_word[index];
+ }
+ }
+ if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
+ appid = g_maclient_info[loop].appid;
+ }
+ }
+ }
+ }
+
+ return appid;
+}
+
+int mas_get_current_client_pid()
+{
+ int ret = -1;
+ if (g_current_maclient_info >= 0 && g_current_maclient_info < MAX_MACLIENT_INFO_NUM) {
+ const char *current_maclient_appid = g_maclient_info[g_current_maclient_info].appid;
+ ma_client_s* client = ma_client_find_by_appid(current_maclient_appid);
+ if (client) {
+ ret = client->pid;
+ }
+ }
+ return ret;
+}
+
+int mas_get_client_pid_by_wakeup_word(const char *wakeup_word)
+{
+ int ret = -1;
+
+ const char *appid = __get_client_appid_by_wakeup_word(wakeup_word);
+ if (appid) {
+ ma_client_s *client = NULL;
+ client = ma_client_find_by_appid(appid);
+ if (client) {
+ ret = client->pid;
+ }
+ }
+
+ return ret;
+}
+
+int mas_set_current_client_by_wakeup_word(const char *wakeup_word)
+{
+ int ret = -1;
+
+ for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
+ if (g_maclient_info[loop].used &&
+ strlen(g_maclient_info[loop].appid) > 0 &&
+ strlen(g_maclient_info[loop].wakeup_word) > 0) {
+ if (0 == strncmp(wakeup_word, g_maclient_info[loop].wakeup_word, MAX_WAKEUP_WORD_LEN)) {
+ g_current_maclient_info = loop;
+ }
+ }
+ }
+ return ret;
+}
+
+int mas_launch_client_by_wakeup_word(const char *wakeup_word)
+{
+ app_control_h app_control;
+ int ret = 0;
+
+ const char *appid = __get_client_appid_by_wakeup_word(wakeup_word);
+ if (NULL == appid || 0 == strlen(appid)) {
+ MAS_LOGW("could not find appropriate appid with wakeup word %s", (wakeup_word ? wakeup_word : "NULL"));
+ return -1;
+ }
+
+ ret = app_control_create(&app_control);
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ MAS_LOGW("app_control_create returned %08x", ret);
+ return -1;
+ }
+
+ ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ MAS_LOGW("app_control_set_operation returned %08x", ret);
+ app_control_destroy(app_control);
+ return -1;
+ }
+
+ /* These extra data key/value should be defined somewhere in multi-assistant framework */
+ ret = app_control_add_extra_data(app_control, "request_speech_data", "true");
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ MAS_LOGW("app_control_add_extra_data returned %08x", ret);
+ app_control_destroy(app_control);
+ return -1;
+ }
+
+ ret = app_control_set_app_id(app_control, appid);
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ MAS_LOGW("app_control_set_app_id returned %08x", ret);
+ app_control_destroy(app_control);
+ return -1;
+ }
+
+ ret = app_control_send_launch_request(app_control, NULL, NULL);
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ MAS_LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, appid);
+ }
+ app_control_destroy (app_control);
+
+ if (APP_CONTROL_ERROR_NONE != ret) {
+ g_launching_maclient_appid = appid;
+ }
+
+ return ret;
+}
bool service_app_create(void *data)
{
{
MAS_LOGD("[ENTER]");
- if (mas_check_client_available()) {
+ char *wakeup_word = (char*)data;
+
+ mas_set_current_client_by_wakeup_word(wakeup_word);
+ if (mas_get_client_pid_by_wakeup_word(wakeup_word) != -1) {
+ MAS_LOGD("MA Client with wakeup word %s exists, requesting speech data", (wakeup_word ? wakeup_word : "NULL"));
int ret = wakeup_service_request_speech_data();
if (0 != ret) {
MAS_LOGE("[ERROR] Fail to request speech data(%d)", ret);
}
} else {
// Appropriate MA Client not available, trying to launch new one
- mas_launch_client();
+ MAS_LOGD("MA Client with wakeup word %s does not exist, launching client", (wakeup_word ? wakeup_word : "NULL"));
+ mas_launch_client_by_wakeup_word(wakeup_word);
}
+ if (wakeup_word) free(wakeup_word);
+
MAS_LOGD("END");
return EINA_FALSE;
}
-
static void __wakeup_event_cb(wakeup_service_wakeup_event_e event, const char* wakeup_word, void* user_data)
{
MAS_LOGD("[SUCCESS] __wakeup_event_cb is called, event(%d), wakeup_word(%s)", event, wakeup_word);
ecore_thread_main_loop_end();
}
#endif /* - TEST_CODE */
- if (WAKEUP_EVENT_SUCCESS == event) {
+ if (WAKEUP_EVENT_SUCCESS == event && wakeup_word) {
ecore_thread_main_loop_begin();
- ecore_timer_add(0.0f, __request_speech_data, NULL);
+ ecore_timer_add(0.0f, __request_speech_data, (void*)strdup(wakeup_word));
ecore_thread_main_loop_end();
}
static void __speech_streaming_cb(wakeup_service_speech_streaming_event_e event, unsigned char* buffer, int len, void *user_data)
{
MAS_LOGD( "[SUCCESS] __speech_streaming_cb is called, event(%d), buffer(%p), len(%d)", event, buffer, len);
- int ret = masc_dbus_send_speech_data(event, buffer, len);
- if (0 != ret) {
- MAS_LOGE("[ERROR] Fail to send speech data, ret(%d)", ret);
+ int pid = mas_get_current_client_pid();
+ if (pid == -1) {
+ MAS_LOGE("[ERROR] Fail to retrieve pid of current MA client");
+ } else {
+ int ret = masc_dbus_send_speech_data(pid, event, buffer, len);
+ if (0 != ret) {
+ MAS_LOGE("[ERROR] Fail to send speech data, ret(%d)", ret);
+ }
}
#ifdef BUF_SAVE_MODE