Terminate service engine when engine is changed
[platform/core/uifw/tts.git] / server / ttse.c
1 /*
2 *  Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include "ttsd_main.h"
16 #include "ttsd_server.h"
17 #include "ttsd_dbus.h"
18 #include "ttsd_ipc.h"
19 #include "ttsd_network.h"
20
21 #include <aul.h>
22 #include <bundle.h>
23 #include <bundle_internal.h>
24 #include <dlog.h>
25 #include <Ecore.h>
26 #include <vconf.h>
27 #include <app_manager.h>
28
29 #include "ttse.h"
30 #include "ttse_internal.h"
31
32 static ttsd_mode_e g_tts_mode = TTSD_MODE_DEFAULT;
33 static bool g_is_terminated = false;
34
35 const char* tts_tag()
36 {
37         if (TTSD_MODE_NOTIFICATION == g_tts_mode) {
38                 return "ttsdnoti";
39         } else if (TTSD_MODE_SCREEN_READER == g_tts_mode) {
40                 return "ttsdsr";
41         } else if (TTSD_MODE_INTERRUPT == g_tts_mode) {
42                 return "ttsdinterrupt";
43         } else {
44                 return "ttsd";
45         }
46 }
47
48 ttsd_mode_e ttsd_get_mode()
49 {
50         return g_tts_mode;
51 }
52
53 void ttsd_set_mode(ttsd_mode_e mode)
54 {
55         g_tts_mode = mode;
56         return;
57 }
58
59 static bool __is_default_engine()
60 {
61         char* engine = NULL;
62         engine = vconf_get_str(VCONFKEY_TTS_ENGINE_DEFAULT);
63         if (NULL == engine) {
64                 SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get sting for vc engine");
65                 return FALSE;
66         }
67
68         char appid[1024] = {'\0', };
69         if (0 != aul_app_get_appid_bypid(getpid(), appid, sizeof(appid) - 1)) {
70                 SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get callee appid by pid");
71         }
72
73         SLOG(LOG_DEBUG, tts_tag(), "[Server] TTS Default Engine(%s), appId(%s)", engine, appid);
74         if (0 == strncmp(engine, appid, strlen(engine))) {
75                 free(engine);
76                 return TRUE;
77         }
78         free(engine);
79         return FALSE;
80 }
81
82 static ttsd_mode_e __get_mode_from_appid()
83 {
84         int pid = getpid();
85         char* appid = NULL;
86         int ret = app_manager_get_app_id(pid, &appid);
87
88         if (0 != ret || NULL == appid) {
89                 return TTSD_MODE_DEFAULT;
90         }
91
92         SLOG(LOG_WARN, tts_tag(), "[WARNING] appid (%s)", appid);
93         char* token = strtok(appid, "-");
94         char* last = NULL;
95         while (NULL != token) {
96                 last = token;
97                 token = strtok(NULL, "-");
98         }
99
100         ttsd_mode_e mode = TTSD_MODE_DEFAULT;
101         if (NULL != last) {
102                 if (!strncmp("noti", last, strlen(last))) {
103                         mode = TTSD_MODE_NOTIFICATION;
104                 } else if (!strncmp("sr", last, strlen(last))) {
105                         mode = TTSD_MODE_SCREEN_READER;
106                 } else if (!strncmp("interrupt", last, strlen(last))) {
107                         mode = TTSD_MODE_INTERRUPT;
108                 } else {
109                         SLOG(LOG_INFO, tts_tag(), "[INFO] mode (%s)", last);
110                 }
111         }
112
113         free(appid);
114
115         return mode;
116 }
117
118 static void __engine_changed_cb(keynode_t* key, void* data)
119 {
120         SLOG(LOG_INFO, tts_tag(), "[INFO] TTS engine vconfkey is changed");
121
122         /* If a new TTS engine is different from the current engine, call ttse_terminate() */
123         if (FALSE == __is_default_engine()) {
124                 SLOG(LOG_WARN, tts_tag(), "[WARNING] TTS engine is changed. Please call ttse_terminate()");
125                 ttse_terminate();
126                 ecore_main_loop_quit();
127         } else {
128                 SLOG(LOG_INFO, tts_tag(), "[INFO] A new TTS engine is same as the current engine.");
129         }
130
131         return;
132 }
133
134 static bool __is_test_app()
135 {
136         char* appid = NULL;
137         int ret = app_manager_get_app_id(getpid(), &appid);
138         if (APP_MANAGER_ERROR_NONE != ret || NULL == appid) {
139                 return false;
140         }
141         SLOG(LOG_INFO, tts_tag(), "[INFO] app id (%s)", appid);
142
143         bool is_test_app = false;
144         if (0 == strncmp(appid, "org.tizen.tts-native-itc", 32) || 0 == strncmp(appid, "org.tizen.tts-native-utc", 32)) {
145                 SLOG(LOG_INFO, tts_tag(), "[INFO] Test mode is on");
146                 is_test_app = true;
147         }
148
149         free(appid);
150         return is_test_app;
151 }
152
153 int ttse_main(int argc, char** argv, ttse_request_callback_s *callback)
154 {
155         bundle *b = NULL;
156         ttsd_mode_e mode = TTSD_MODE_DEFAULT;
157         int ret = TTSE_ERROR_NONE;
158         g_is_terminated = false;
159
160         b = bundle_import_from_argv(argc, argv);
161         if (NULL != b) {
162                 char *val = NULL;
163                 if (0 == bundle_get_str(b, "mode", &val)) {
164                         if (NULL != val) {
165                                 if (!strcmp("noti", val)) {
166                                         mode = TTSD_MODE_NOTIFICATION;
167                                 } else if (!strcmp("sr", val)) {
168                                         mode = TTSD_MODE_SCREEN_READER;
169                                 } else if (!strcmp("interrupt", val)) {
170                                         mode = TTSD_MODE_INTERRUPT;
171                                 } else {
172                                         SLOG(LOG_WARN, tts_tag(), "[WARNING] mode (%s)", val);
173                                 }
174                         } else {
175                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] NULL data");
176                         }
177                 } else {
178                         SLOG(LOG_INFO, tts_tag(), "[INFO] Get mode value from app ID");
179                         mode = __get_mode_from_appid();
180                 }
181
182                 bundle_free(b);
183                 val = NULL;
184         } else {
185                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get bundle");
186         }
187
188         ttsd_set_mode(mode);
189
190         SLOG(LOG_DEBUG, tts_tag(), "Start engine as [%d] mode", mode);
191
192         if (!ecore_init()) {
193                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to initialize Ecore");
194                 return TTSE_ERROR_OPERATION_FAILED;
195         }
196
197         ret = ttsd_initialize(callback);
198         if (0 != ret) {
199                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to initialize");
200                 ecore_shutdown();
201                 return ret;
202         }
203
204         if (TRUE == __is_default_engine()) {
205                 if (0 != ttsd_ipc_open_connection()) {
206                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to open ipc connection");
207                         ecore_shutdown();
208                         return TTSE_ERROR_OPERATION_FAILED;
209                 }
210         }
211
212         if (0 != ttsd_network_initialize()) {
213                 SLOG(LOG_WARN, tts_tag(), "[WARNING] Fail to initialize network");
214         }
215
216         /* If a new TTS engine is different from the current engine, call ttse_terminate() */
217         if (FALSE == __is_default_engine() && !__is_test_app()) {
218                 SLOG(LOG_WARN, tts_tag(), "[WARNING] TTS engine is changed. Please call ttse_terminate()");
219                 ttse_terminate();
220                 return TTSE_ERROR_NONE;
221         }
222
223         /* Register vconfkey callback to detect engine change */
224         vconf_notify_key_changed(TTS_ENGINE_DB_DEFAULT, __engine_changed_cb, NULL);
225
226         SLOG(LOG_DEBUG, tts_tag(), "@@@");
227
228         return TTSE_ERROR_NONE;
229 }
230
231 int ttse_terminate()
232 {
233         if (true == g_is_terminated) {
234                 SLOG(LOG_INFO, tts_tag(), "[INFO] ttse_terminate() is already invoked.");
235                 return TTSE_ERROR_NONE;
236         }
237
238         g_is_terminated = true;
239         ttsd_terminate();
240
241         /* Unregister vconfkey callback */
242         vconf_ignore_key_changed(TTS_ENGINE_DB_DEFAULT, __engine_changed_cb);
243
244         return TTSE_ERROR_NONE;
245 }
246
247 int ttse_get_speed_range(int* min, int* normal, int* max)
248 {
249         if (NULL == min || NULL == normal || NULL == max) {
250                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is null");
251                 return TTSE_ERROR_INVALID_PARAMETER;
252         }
253
254         *min = TTS_SPEED_MIN;
255         *normal = TTS_SPEED_NORMAL;
256         *max = TTS_SPEED_MAX;
257
258         return 0;
259 }
260
261 int ttse_get_pitch_range(int* min, int* normal, int* max)
262 {
263         if (NULL == min || NULL == normal || NULL == max) {
264                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is null");
265                 return TTSE_ERROR_INVALID_PARAMETER;
266         }
267
268         *min = TTS_PITCH_MIN;
269         *normal = TTS_PITCH_NORMAL;
270         *max = TTS_PITCH_MAX;
271
272         return 0;
273 }
274
275 int ttse_send_result(ttse_result_event_e event, const void* data, unsigned int data_size, ttse_audio_type_e audio_type, int rate, void* user_data)
276 {
277         int ret;
278
279         if (NULL == data) {
280                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is null");
281         }
282
283         ret = ttsd_send_result(event, data, data_size, audio_type, rate, user_data);
284
285         if (0 != ret) {
286                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to send result");
287         }
288
289         return ret;
290 }
291
292 int ttse_send_error(ttse_error_e error, const char* msg)
293 {
294         int ret;
295
296         ret = ttsd_send_error(error, msg);
297
298         if (0 != ret) {
299                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to send error");
300         }
301
302         return ret;
303 }
304
305 int ttse_set_private_data_set_cb(ttse_private_data_set_cb callback_func)
306 {
307         if (NULL == callback_func) {
308                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid parameter");
309                 return TTSE_ERROR_INVALID_PARAMETER;
310         }
311
312         int ret = ttsd_set_private_data_set_cb(callback_func);
313
314         if (0 != ret) {
315                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to set private data set cb");
316         }
317
318         return ret;
319 }
320
321 int ttse_set_private_data_requested_cb(ttse_private_data_requested_cb callback_func)
322 {
323         if (NULL == callback_func) {
324                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid parameter");
325                 return TTSE_ERROR_INVALID_PARAMETER;
326         }
327
328         int ret = ttsd_set_private_data_requested_cb(callback_func);
329
330         if (0 != ret) {
331                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to set private data requested cb");
332         }
333
334         return ret;
335 }