dbus-1
glib-2.0
message-port
+ libxml-2.0
)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/inc)
-SET(SRCS src/multi_assistant_service.c
+SET(SRCS
+ src/multi_assistant_config.c
+ src/multi_assistant_service.c
src/multi_assistant_service_plugin.c
src/multi_assistant_dbus.c
src/multi_assistant_dbus_server.c
--- /dev/null
+/**
+ * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd 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.
+ */
+
+
+#ifndef __MULTI_ASSISTANT_CONFIG_H__
+#define __MULTI_ASSISTANT_CONFIG_H__
+
+#include <tzplatform_config.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MAX_WAKEUP_LIST_NUM 32
+#define MAX_SUPPORTED_LANGUAGE_NUM 128
+
+/**************************************************************************************
+ *** Definitions for xml file
+ *************************************************************************************/
+#define MA_TAG_ASSISTANT_BASE "multi-assistant"
+#define MA_TAG_ASSISTANT_NAME "name"
+#define MA_TAG_ASSISTANT_ID "id"
+#define MA_TAG_ASSISTANT_ICON_PATH "icon-path"
+#define MA_TAG_ASSISTANT_LANGUAGE_SET "languages"
+#define MA_TAG_ASSISTANT_LANGUAGE "lang"
+#define MA_TAG_ASSISTANT_WAKEUP_WORD_SET "wakeup-words"
+#define MA_TAG_ASSISTANT_WAKEUP_WORD "wakeup-word"
+
+/**************************************************************************************
+ *** Definitions for ETC
+ *************************************************************************************/
+#define MA_RETRY_COUNT 5
+
+#define MA_ASSISTANT_INFO tzplatform_mkpath(TZ_USER_HOME, "share/.multiassistant/ma/1.0/assistant-info")
+
+typedef struct {
+ const char* app_id;
+ const char* name;
+ const char* icon_path;
+ const char* wakeup_list[MAX_WAKEUP_LIST_NUM];
+ int cnt_wakeup;
+ const char* supported_lang[MAX_SUPPORTED_LANGUAGE_NUM];
+ int cnt_lang;
+} ma_assistant_info_s;
+
+typedef int (*mas_config_assistant_info_cb)(const char* appid, const char* name, const char* icon_path, const char* wakeup_list[], int cnt_wakeup, const char* supported_lang[], int cnt_lang, void* user_data);
+int mas_config_get_assistant_info(mas_config_assistant_info_cb callback, void* user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MULTI_ASSISTANT_CONFIG_H__ */
\ No newline at end of file
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(message-port)
+BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: boost-system
BuildRequires: boost-thread
--- /dev/null
+/**
+ * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd 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.
+ */
+
+#include <libxml/parser.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "multi_assistant_config.h"
+#include "multi_assistant_main.h"
+
+int mas_config_parse_assistant_info(mas_config_assistant_info_cb callback, const char *path, void* user_data)
+{
+ xmlDocPtr doc = NULL;
+ xmlNodePtr cur = NULL;
+ xmlChar *key;
+
+ int loop;
+ int retry_count = 0;
+
+ while (NULL == doc) {
+ doc = xmlParseFile(path);
+ if (NULL != doc) {
+ break;
+ }
+
+ if (MA_RETRY_COUNT == retry_count++) {
+ MAS_LOGE("[ERROR] Fail to parse file error : %s", path);
+ xmlCleanupParser();
+ return -1;
+ }
+ usleep(10000);
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ MAS_LOGE("[ERROR] Empty document");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) MA_TAG_ASSISTANT_BASE)) {
+ MAS_LOGE("[ERROR] The wrong type, root node is NOT %s", MA_TAG_ASSISTANT_BASE);
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ cur = cur->xmlChildrenNode;
+ if (cur == NULL) {
+ MAS_LOGE("[ERROR] Empty document");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ /* alloc assistant info */
+ ma_assistant_info_s* temp;
+ temp = (ma_assistant_info_s*)calloc(1, sizeof(ma_assistant_info_s));
+ if (NULL == temp) {
+ MAS_LOGE("[ERROR] Fail to allocate memory");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ temp->app_id = NULL;
+ temp->name = NULL;
+ temp->icon_path = NULL;
+ memset(temp->wakeup_list, 0x00, sizeof(temp->wakeup_list));
+ temp->cnt_wakeup = 0;
+ memset(temp->supported_lang, 0x00, sizeof(temp->supported_lang));
+ temp->cnt_lang = 0;
+
+ while (cur != NULL) {
+ if (cur->name && 0 == xmlStrcmp(cur->name, (const xmlChar *)MA_TAG_ASSISTANT_LANGUAGE_SET)) {
+ xmlNodePtr child_node = cur->xmlChildrenNode;
+ while (child_node != NULL) {
+ if (child_node->name && 0 == xmlStrcmp(child_node->name, (const xmlChar*)MA_TAG_ASSISTANT_LANGUAGE)) {
+ key = xmlNodeGetContent(child_node);
+ if (key) {
+ temp->supported_lang[temp->cnt_lang++] = strdup((const char*)key);
+ MAS_LOGD("Language : %s", key);
+ xmlFree(key);
+ }
+ }
+
+ child_node = child_node->next;
+ }
+ } else if (cur->name && 0 == xmlStrcmp(cur->name, (const xmlChar *)MA_TAG_ASSISTANT_WAKEUP_WORD_SET)) {
+ xmlNodePtr child_node = cur->xmlChildrenNode;
+ while (child_node != NULL) {
+ if (child_node->name && 0 == xmlStrcmp(child_node->name, (const xmlChar*)MA_TAG_ASSISTANT_WAKEUP_WORD)) {
+ key = xmlNodeGetContent(child_node);
+ if (key) {
+ temp->wakeup_list[temp->cnt_wakeup++] = strdup((const char*)key);
+ MAS_LOGD("Wakeup Word : %s", key);
+ xmlFree(key);
+ }
+ }
+
+ child_node = child_node->next;
+ }
+ } else if (cur->name && 0 == xmlStrcmp(cur->name, (const xmlChar*)MA_TAG_ASSISTANT_NAME)) {
+ key = xmlNodeGetContent(cur);
+ if (key) {
+ temp->name = strdup((const char*)key);
+ MAS_LOGD("Name : %s", key);
+ xmlFree(key);
+ }
+ } else if (cur->name && 0 == xmlStrcmp(cur->name, (const xmlChar*)MA_TAG_ASSISTANT_ID)) {
+ key = xmlNodeGetContent(cur);
+ if (key) {
+ temp->app_id = strdup((const char*)key);
+ MAS_LOGD("ID : %s", key);
+ xmlFree(key);
+ }
+ } else if (cur->name && 0 == xmlStrcmp(cur->name, (const xmlChar*)MA_TAG_ASSISTANT_ICON_PATH)) {
+ key = xmlNodeGetContent(cur);
+ if (key) {
+ temp->icon_path = strdup((const char*)key);
+ MAS_LOGD("Icon Path : %s", key);
+ xmlFree(key);
+ }
+ }
+
+ cur = cur->next;
+ }
+
+ if (callback) {
+ callback(temp->app_id, temp->name, temp->icon_path,
+ temp->wakeup_list, temp->cnt_wakeup, temp->supported_lang, temp->cnt_lang, user_data);
+ }
+
+ if (temp->app_id) {
+ free((void*)temp->app_id);
+ }
+ if (temp->name) {
+ free((void*)temp->name);
+ }
+ if (temp->icon_path) {
+ free((void*)temp->icon_path);
+ }
+ for (loop = 0; loop < temp->cnt_wakeup; loop++) {
+ if (temp->wakeup_list[loop]) {
+ free((void*)(temp->wakeup_list[loop]));
+ }
+ }
+ for (loop = 0; loop < temp->cnt_lang; loop++) {
+ if (temp->supported_lang[loop]) {
+ free((void*)(temp->supported_lang[loop]));
+ }
+ }
+
+ free(temp);
+ xmlFreeDoc(doc);
+
+ return 0;
+}
+
+int mas_config_get_assistant_info(mas_config_assistant_info_cb callback, void* user_data)
+{
+ const char *suffix = ".xml";
+
+ DIR *d;
+ struct dirent *dir;
+ d = opendir(MA_ASSISTANT_INFO);
+
+ if (d) {
+ while (NULL != (dir = readdir(d))) {
+ if (suffix && dir->d_name && strlen(suffix) <= strlen(dir->d_name)) {
+ if (0 == strcmp(dir->d_name + strlen(dir->d_name) - strlen(suffix), suffix)) {
+ char fullpath[_POSIX_PATH_MAX];
+ snprintf(fullpath, _POSIX_PATH_MAX - 1, "%s/%s", MA_ASSISTANT_INFO, dir->d_name);
+ MAS_LOGD("Parsing file : %s\n", fullpath);
+ mas_config_parse_assistant_info(callback, fullpath, user_data);
+ }
+ }
+ }
+ closedir(d);
+ }
+
+ return 0;
+}
\ No newline at end of file
#include "multi_assistant_service.h"
#include "multi_assistant_service_plugin.h"
#include "multi_assistant_dbus.h"
+#include "multi_assistant_config.h"
static const char *g_current_lang = "en_US";
static int g_local_port_id = -1;
#define MAX_MACLIENT_INFO_NUM 16
+#define MAX_WAKEUP_WORDS_NUM 4
#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];
+ char appid[MAX_APPID_LEN];
+ char wakeup_word[MAX_WAKEUP_WORDS_NUM][MAX_WAKEUP_WORD_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"}},
-};
+static ma_client_info g_maclient_info[MAX_MACLIENT_INFO_NUM];
typedef struct {
int pid;
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) {
+ strlen(g_maclient_info[loop].wakeup_word[0]) > 0) {
if (strncmp(appid, g_maclient_info[loop].appid, MAX_APPID_LEN) == 0) {
mas_launch_client_by_appid(g_maclient_info[loop].appid);
}
message_port_unregister_local_port(g_local_port_id);
}
+int __mas_assistant_info_cb(const char* appid, const char* name,
+ const char* icon_path, const char* wakeup_list[], int cnt_wakeup,
+ const char* supported_lang[], int cnt_lang, void* user_data) {
+ MAS_LOGD("__mas_assistant_info_cb called");
+
+ if (NULL == appid) {
+ MAS_LOGD("app_id NULL, returning");
+ return -1;
+ }
+
+ int index = -1;
+ int loop = 0;
+ while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
+ if (EINA_FALSE == g_maclient_info[loop].used) {
+ index = loop;
+ }
+ loop++;
+ }
+ if (-1 != index) {
+ g_maclient_info[index].used = EINA_TRUE;
+ MAS_LOGD("app_id(%s)", appid);
+ strncpy(g_maclient_info[index].appid, appid, MAX_APPID_LEN);
+ g_maclient_info[index].appid[MAX_APPID_LEN - 1] = '\0';
+
+ for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
+ if (loop < cnt_wakeup && wakeup_list[loop]) {
+ MAS_LOGD("wakeup_list(%d)(%s)", loop, wakeup_list[loop]);
+ strncpy(g_maclient_info[index].wakeup_word[loop], wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
+ g_maclient_info[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
+ } else {
+ strncpy(g_maclient_info[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
+ }
+ }
+ } else {
+ MAS_LOGD("Couldn't find an empty slot for storing assistant info");
+ }
+
+ MAS_LOGD("__mas_assistant_info_cb end");
+
+ return 0;
+}
+
+
static int init_wakeup(void)
{
MAS_LOGD("[Enter] init_wakeup ");
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 == mas_config_get_assistant_info(__mas_assistant_info_cb, NULL)) {
+ for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
+ if (g_maclient_info[loop].used &&
+ strlen(g_maclient_info[loop].appid) > 0) {
+ for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
+ if (strlen(g_maclient_info[loop].wakeup_word[inner_loop]) > 0) {
+ MAS_LOGD("Registering wakeup word %s for app %s",
+ g_maclient_info[loop].wakeup_word[inner_loop], g_maclient_info[loop].appid);
+ if (0 != multi_assistant_service_plugin_set_wakeup_word(
+ "en_US", g_maclient_info[loop].wakeup_word[inner_loop])) {
+ MAS_LOGE("Fail to stt wakeup word");
+ }
+ }
+ }
}
}
+ } else {
+ MAS_LOGE("Fail to load assistant info");
}
if (0 != multi_assistant_service_plugin_set_callbacks()) {
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;
+ strlen(g_maclient_info[loop].appid) > 0) {
+ for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
+ if (strlen(g_maclient_info[loop].wakeup_word[inner_loop]) > 0) {
+ if (0 == strncmp(wakeup_word, g_maclient_info[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
+ appid = g_maclient_info[loop].appid;
+ }
+ }
}
}
}
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];
+ strlen(g_maclient_info[loop].appid) > 0) {
+ for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
+ if (strlen(g_maclient_info[loop].wakeup_word[inner_loop]) > 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[inner_loop][index]) {
+ comparand[comparand_index++] = g_maclient_info[loop].wakeup_word[inner_loop][index];
+ }
+ }
+ if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
+ appid = g_maclient_info[loop].appid;
+ }
}
}
- if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
- appid = g_maclient_info[loop].appid;
- }
}
}
}
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;
+ strlen(g_maclient_info[loop].appid) > 0) {
+ for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
+ if (strlen(g_maclient_info[loop].wakeup_word[inner_loop]) > 0) {
+ if (0 == strncmp(wakeup_word, g_maclient_info[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
+ g_current_maclient_info = loop;
+ }
+ }
}
}
}
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) {
+ strlen(g_maclient_info[loop].wakeup_word[0]) > 0) {
if (strncmp(appid, g_maclient_info[loop].appid, MAX_APPID_LEN) == 0) {
g_current_maclient_info = loop;
}