Fix PLM issue(P130121-3243) and Add Daemon termination
[platform/core/uifw/tts.git] / client / tts.c
1 /*
2 *  Copyright (c) 2012, 2013 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 <sys/wait.h>
16 #include <Ecore.h>
17 #include <sys/stat.h>
18 #include <sys/types.h> 
19 #include <dirent.h>
20
21 #include "tts_main.h"
22 #include "tts_client.h"
23 #include "tts_dbus.h"
24
25 #define MAX_TEXT_COUNT 1000
26
27 static bool g_is_daemon_started = false;
28
29 /* Function definition */
30 static int __tts_check_tts_daemon();
31 static Eina_Bool __tts_notify_state_changed(void *data);
32 static Eina_Bool __tts_notify_error(void *data);
33
34 int tts_create(tts_h* tts)
35 {
36         SLOG(LOG_DEBUG, TAG_TTSC, "===== Create TTS");
37         
38         /* check param */
39         if (NULL == tts) {
40                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
41                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
42                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
43                 return TTS_ERROR_INVALID_PARAMETER;
44         }       
45
46         if (0 == tts_client_get_size()) {
47                 if (0 != tts_dbus_open_connection()) {
48                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to open dbus connection");
49                         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
50                         SLOG(LOG_DEBUG, TAG_TTSC, " ");
51                         return TTS_ERROR_OPERATION_FAILED;
52                 }
53         }
54
55         if (0 != tts_client_new(tts)) {
56                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create client!!!!!");
57                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
58                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
59                 return TTS_ERROR_OUT_OF_MEMORY;
60         }
61
62         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
63         SLOG(LOG_DEBUG, TAG_TTSC, " ");
64
65         return TTS_ERROR_NONE;
66 }
67
68 int tts_destroy(tts_h tts)
69 {
70         SLOG(LOG_DEBUG, TAG_TTSC, "===== Destroy TTS");
71
72         if (NULL == tts) {
73                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
74                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
75                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
76                 return TTS_ERROR_INVALID_PARAMETER;
77         }
78
79         tts_client_s* client = tts_client_get(tts);
80
81         /* check handle */
82         if (NULL == client) {
83                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
84                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
85                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
86                 return TTS_ERROR_INVALID_PARAMETER;
87         }
88
89         int ret = -1;
90
91         /* check state */
92         switch (client->current_state) {
93         case TTS_STATE_PAUSED:
94         case TTS_STATE_PLAYING:
95         case TTS_STATE_READY:
96                 /* Request Finalize */
97                 ret = tts_dbus_request_finalize(client->uid);
98                 if (0 != ret) {
99                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request finalize");
100                 }
101                 g_is_daemon_started = false;
102         case TTS_STATE_CREATED:
103                 /* Free resources */
104                 tts_client_destroy(tts);
105                 break;
106         }
107  
108         if (0 == tts_client_get_size()) {
109                 if (0 != tts_dbus_close_connection()) {
110                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to close connection");
111                 }
112         }
113
114         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
115         SLOG(LOG_DEBUG, TAG_TTSC, " ");
116
117         return TTS_ERROR_NONE;
118 }
119
120 static Eina_Bool __tts_connect_daemon(void *data)
121 {
122         SLOG(LOG_DEBUG, TAG_TTSC, "===== Connect daemon");
123
124         tts_h tts = (tts_h)data;
125
126         tts_client_s* client = tts_client_get(tts);
127
128         /* check handle */
129         if (NULL == client) {
130                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
131                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
132                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
133                 return EINA_FALSE;
134         }
135
136         /* Send hello */
137         if (0 != tts_dbus_request_hello()) {
138                 if (false == g_is_daemon_started) {
139                         g_is_daemon_started = true;
140                         __tts_check_tts_daemon();
141                 }
142                 return EINA_TRUE;
143         }
144
145         /* do request initialize */
146         int ret = -1;
147
148         ret = tts_dbus_request_initialize(client->uid);
149
150         if (TTS_ERROR_ENGINE_NOT_FOUND == ret) {
151                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine not found");
152                 
153                 client->reason = TTS_ERROR_ENGINE_NOT_FOUND;
154                 client->utt_id = -1;
155
156                 ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
157                 return EINA_FALSE;
158
159         } else if (TTS_ERROR_NONE != ret) {
160                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connection");
161
162                 client->reason = TTS_ERROR_TIMED_OUT;
163                 client->utt_id = -1;
164
165                 ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
166                 return EINA_FALSE;
167         } else {
168                 /* success to connect tts-daemon */
169         }
170
171         client->before_state = client->current_state;
172         client->current_state = TTS_STATE_READY;
173
174         ecore_timer_add(0, __tts_notify_state_changed, (void*)client->tts);
175
176         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] uid(%d)", client->uid);
177
178         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
179         SLOG(LOG_DEBUG, TAG_TTSC, " ");
180
181         return EINA_FALSE;
182 }
183
184
185 int tts_prepare(tts_h tts)
186 {
187         SLOG(LOG_DEBUG, TAG_TTSC, "===== Prepare TTS");
188
189         tts_client_s* client = tts_client_get(tts);
190
191         /* check handle */
192         if (NULL == client) {
193                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not available");
194                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
195                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
196                 return TTS_ERROR_INVALID_PARAMETER;
197         }
198
199         /* check state */
200         if (client->current_state != TTS_STATE_CREATED) {
201                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid State: Current state is not 'CREATED'"); 
202                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
203                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
204                 return TTS_ERROR_INVALID_STATE;
205         }
206
207         ecore_timer_add(0, __tts_connect_daemon, (void*)tts);
208
209         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
210         SLOG(LOG_DEBUG, TAG_TTSC, " ");
211
212         return TTS_ERROR_NONE;
213 }
214
215 int tts_unprepare(tts_h tts)
216 {
217         SLOG(LOG_DEBUG, TAG_TTSC, "===== Unprepare TTS");
218
219         tts_client_s* client = tts_client_get(tts);
220
221         /* check handle */
222         if (NULL == client) {
223                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not available");
224                 return TTS_ERROR_INVALID_PARAMETER;
225         }
226
227         /* check state */
228         if (client->current_state != TTS_STATE_READY) {
229                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid State: Current state is not 'READY'"); 
230                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
231                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
232                 return TTS_ERROR_INVALID_STATE;
233         }
234
235         int ret = tts_dbus_request_finalize(client->uid);
236         if (0 != ret) {
237                 SLOG(LOG_WARN, TAG_TTSC, "[ERROR] Fail to request finalize");
238         }
239         g_is_daemon_started = false;
240
241         client->before_state = client->current_state;
242         client->current_state = TTS_STATE_CREATED;
243
244         ecore_timer_add(0, __tts_notify_state_changed, (void*)tts);
245
246         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
247         SLOG(LOG_DEBUG, TAG_TTSC, " ");
248
249         return TTS_ERROR_NONE;
250 }
251
252 int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data)
253 {
254         SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported voices");
255
256         if (NULL == tts || NULL == callback) {
257                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
258                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
259                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
260                 return TTS_ERROR_INVALID_PARAMETER;
261         }
262
263         tts_client_s* client = tts_client_get(tts);
264
265         /* check handle */
266         if (NULL == client) {
267                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
268                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
269                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
270                 return TTS_ERROR_INVALID_PARAMETER;
271         }
272
273         if (TTS_STATE_READY != client->current_state) {
274                 SLOG(LOG_ERROR, TAG_TTSC, "Current state is NOT 'READY'.");  
275                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
276                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
277                 return TTS_ERROR_INVALID_STATE;
278         }
279
280         int ret = 0;
281         ret = tts_dbus_request_get_support_voice(client->uid, client->tts, callback, user_data);
282         if (0 != ret) {
283                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
284         }    
285
286         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
287         SLOG(LOG_DEBUG, TAG_TTSC, " ");
288
289         return ret;
290 }
291
292 int tts_get_default_voice(tts_h tts, char** lang, tts_voice_type_e* vctype)
293 {
294         SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default voice");
295
296         if (NULL == tts) {
297                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
298                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
299                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
300                 return TTS_ERROR_INVALID_PARAMETER;
301
302         }
303         tts_client_s* client = tts_client_get(tts);
304
305         if (NULL == client) {
306                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
307                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
308                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
309                 return TTS_ERROR_INVALID_PARAMETER;
310         }
311
312         if (TTS_STATE_READY != client->current_state) {
313                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is NOT 'READY'. ");
314                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
315                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
316                 return TTS_ERROR_INVALID_STATE;
317         }
318
319         /* Request call remote method */
320         int ret = 0;
321         ret = tts_dbus_request_get_default_voice(client->uid, lang, vctype );
322     
323         if (0 != ret) {
324                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
325         }
326         
327         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
328         SLOG(LOG_DEBUG, TAG_TTSC, " ");
329
330         return ret;
331 }
332
333 int tts_get_max_text_count(tts_h tts, int* count)
334 {
335         if (NULL == tts || NULL == count) {
336                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Input parameter is null");
337                 return TTS_ERROR_INVALID_PARAMETER;
338         }
339
340         tts_client_s* client = tts_client_get(tts);
341
342         if (NULL == client) {
343                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : A handle is not valid");
344                 return TTS_ERROR_INVALID_PARAMETER;
345         }
346         
347         if (TTS_STATE_READY != client->current_state) {
348                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Current state is NOT 'READY'."); 
349                 return TTS_ERROR_INVALID_STATE;
350         }
351
352         *count = MAX_TEXT_COUNT;
353
354         SLOG(LOG_DEBUG, TAG_TTSC, "[Suceess] Get max text count");
355         return TTS_ERROR_NONE;
356 }
357
358 int tts_get_state(tts_h tts, tts_state_e* state)
359 {
360         if (NULL == tts || NULL == state) {
361                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : Input parameter is null");
362                 return TTS_ERROR_INVALID_PARAMETER;
363         }
364
365         tts_client_s* client = tts_client_get(tts);
366
367         if (NULL == client) {
368                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : A handle is not valid");
369                 return TTS_ERROR_INVALID_PARAMETER;
370         }
371
372         *state = client->current_state;
373
374         switch(*state) {
375                 case TTS_STATE_CREATED: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Created'");        break;
376                 case TTS_STATE_READY:   SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Ready'");          break;
377                 case TTS_STATE_PLAYING: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Playing'");        break;
378                 case TTS_STATE_PAUSED:  SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Paused'");         break;
379         }
380
381         return TTS_ERROR_NONE;
382 }
383
384 int tts_add_text(tts_h tts, const char* text, const char* language, tts_voice_type_e voice_type, tts_speed_e speed, int* utt_id)
385 {
386         SLOG(LOG_DEBUG, TAG_TTSC, "===== Add text");
387
388         if (NULL == tts || NULL == utt_id) {
389                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
390                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
391                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
392                 return TTS_ERROR_INVALID_PARAMETER;
393         }
394
395         tts_client_s* client = tts_client_get(tts);
396
397         if (NULL == client) {
398                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
399                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
400                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
401                 return TTS_ERROR_INVALID_PARAMETER;
402         }
403
404         if (TTS_STATE_CREATED == client->current_state) {
405                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is 'CREATED'."); 
406                 return TTS_ERROR_INVALID_STATE;
407         }
408
409         /* change default language value */
410         char* temp = NULL;
411
412         if (NULL == language)
413                 temp = strdup("default");
414         else 
415                 temp = strdup(language);
416
417         client->current_utt_id ++;
418         if (client->current_utt_id == 10000) {
419                 client->current_utt_id = 1;
420         }
421
422         /* do request */
423         int ret = 0;
424         ret = tts_dbus_request_add_text(client->uid, text, temp, voice_type, speed, client->current_utt_id);
425         if (0 != ret) {
426                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
427         }
428
429         *utt_id = client->current_utt_id;
430
431         if (NULL != temp)
432                 free(temp);
433
434         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
435         SLOG(LOG_DEBUG, TAG_TTSC, " ");
436
437         return ret;
438 }
439
440 int tts_play(tts_h tts)
441 {
442         SLOG(LOG_DEBUG, TAG_TTSC, "===== Play tts");
443
444         if (NULL == tts) {
445                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null.");
446                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
447                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
448                 return TTS_ERROR_INVALID_PARAMETER;
449         }
450
451         tts_client_s* client = tts_client_get(tts);
452
453         if (NULL == client) {
454                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid.");
455                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
456                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
457                 return TTS_ERROR_INVALID_PARAMETER;
458         }
459
460         if (TTS_STATE_PLAYING == client->current_state || TTS_STATE_CREATED == client->current_state) {
461                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid."); 
462                 return TTS_ERROR_INVALID_STATE;
463         } 
464
465         int ret = 0;
466         ret = tts_dbus_request_play(client->uid);
467         if (0 != ret) {
468                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Request play : result(%d)", ret);
469                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
470                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
471                 return ret;
472         }
473
474         client->before_state = client->current_state;
475         client->current_state = TTS_STATE_PLAYING;
476
477         if (NULL != client->state_changed_cb) {
478                 ecore_timer_add(0, __tts_notify_state_changed, (void*)tts);
479         } else {
480                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null");
481         }
482
483         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
484         SLOG(LOG_DEBUG, TAG_TTSC, " ");
485
486         return TTS_ERROR_NONE;
487 }
488
489
490 int tts_stop(tts_h tts)
491 {
492         SLOG(LOG_DEBUG, TAG_TTSC, "===== Stop tts");
493
494         if (NULL == tts) {
495                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
496                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
497                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
498                 return TTS_ERROR_INVALID_PARAMETER;
499         }
500
501         tts_client_s* client = tts_client_get(tts);
502
503         if (NULL == client) {
504                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
505                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
506                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
507                 return TTS_ERROR_INVALID_PARAMETER;
508         }
509
510         if (TTS_STATE_CREATED == client->current_state) {
511                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is 'CREATED'."); 
512                 return TTS_ERROR_INVALID_STATE;
513         }
514
515         int ret = 0;
516         ret = tts_dbus_request_stop(client->uid);
517         if (0 != ret) {
518                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
519                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
520                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
521                 return ret;
522         }       
523
524         client->before_state = client->current_state;
525         client->current_state = TTS_STATE_READY;
526
527         if (NULL != client->state_changed_cb) {
528                 ecore_timer_add(0, __tts_notify_state_changed, (void*)tts);
529         } else {
530                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null");
531         }
532
533         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
534         SLOG(LOG_DEBUG, TAG_TTSC, " ");
535
536         return TTS_ERROR_NONE;
537 }
538
539
540 int tts_pause(tts_h tts)
541 {
542         SLOG(LOG_DEBUG, TAG_TTSC, "===== Pause tts");
543
544         if (NULL == tts) {
545                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
546                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
547                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
548                 return TTS_ERROR_INVALID_PARAMETER;
549         }
550
551         tts_client_s* client = tts_client_get(tts);
552
553         if (NULL == client) {
554                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
555                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
556                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
557                 return TTS_ERROR_INVALID_PARAMETER;
558         }
559
560         if (TTS_STATE_PLAYING != client->current_state) {
561                 SLOG(LOG_ERROR, TAG_TTSC, "[Error] The Current state is NOT 'playing'. So this request should be not running.");    
562                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
563                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
564                 return TTS_ERROR_INVALID_STATE;
565         }       
566         
567         int ret = 0;
568         ret = tts_dbus_request_pause(client->uid);
569         if (0 != ret) {
570                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Request pause : result(%d)", ret);
571                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
572                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
573                 return ret;
574         }
575
576         client->before_state = client->current_state;
577         client->current_state = TTS_STATE_PAUSED;
578
579         if (NULL != client->state_changed_cb) {
580                 ecore_timer_add(0, __tts_notify_state_changed, (void*)tts);
581         } else {
582                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null");
583         }
584
585         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
586         SLOG(LOG_DEBUG, TAG_TTSC, " ");
587
588         return TTS_ERROR_NONE;
589 }
590
591 static Eina_Bool __tts_notify_error(void *data)
592 {
593         tts_h tts = (tts_h)data;
594
595         tts_client_s* client = tts_client_get(tts);
596
597         /* check handle */
598         if (NULL == client) {
599                 SLOG(LOG_WARN, TAG_TTSC, "Fail to notify error msg : A handle is not valid");
600                 return EINA_FALSE;
601         }
602
603         if (NULL != client->error_cb) {
604                 SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of error");
605                 tts_client_use_callback(client);
606                 client->error_cb(client->tts, client->utt_id, client->reason, client->error_user_data );
607                 tts_client_not_use_callback(client);
608         } else {
609                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of error ");
610         }
611
612         return EINA_FALSE;
613 }
614
615 int __tts_cb_error(int uid, tts_error_e reason, int utt_id)
616 {
617         tts_client_s* client = tts_client_get_by_uid(uid);
618
619         if (NULL == client) {
620                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] A handle is not valid");
621                 return TTS_ERROR_INVALID_PARAMETER;
622         }
623
624         client->utt_id = utt_id;
625         client->reason = reason;
626
627         /* call callback function */
628         if (NULL != client->error_cb) {
629                 ecore_timer_add(0, __tts_notify_error, client->tts);
630         } else {
631                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of error ");
632         }
633         
634         return 0;
635 }
636
637 static Eina_Bool __tts_notify_state_changed(void *data)
638 {
639         tts_h tts = (tts_h)data;
640
641         tts_client_s* client = tts_client_get(tts);
642
643         /* check handle */
644         if (NULL == client) {
645                 SLOG(LOG_WARN, TAG_TTSC, "Fail to notify state changed : A handle is not valid");
646                 return EINA_FALSE;
647         }
648
649         if (NULL != client->state_changed_cb) {
650                 tts_client_use_callback(client);
651                 client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data); 
652                 tts_client_not_use_callback(client);
653                 SLOG(LOG_DEBUG, TAG_TTSC, "State changed callback is called");
654         } else {
655                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null");
656         }
657
658         return EINA_FALSE;
659 }
660
661 int __tts_cb_set_state(int uid, int state)
662 {
663         tts_client_s* client = tts_client_get_by_uid(uid);
664         if( NULL == client ) {
665                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] The handle is not valid");
666                 return -1;
667         }
668
669         tts_state_e state_from_daemon = (tts_state_e)state;
670
671         if (client->current_state == state_from_daemon) {
672                 SLOG(LOG_DEBUG, TAG_TTSC, "Current state has already been %d", client->current_state);
673                 return 0;
674         }
675
676         if (NULL != client->state_changed_cb) {
677                 ecore_timer_add(0, __tts_notify_state_changed, client->tts);
678         } else {
679                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null");
680         }
681
682         client->before_state = client->current_state;
683         client->current_state = state_from_daemon;
684
685         return 0;
686 }
687
688 static Eina_Bool __tts_notify_utt_started(void *data)
689 {
690         tts_h tts = (tts_h)data;
691
692         tts_client_s* client = tts_client_get(tts);
693
694         /* check handle */
695         if (NULL == client) {
696                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to notify utt started : A handle is not valid");
697                 return EINA_FALSE;
698         }
699         
700         if (NULL != client->utt_started_cb) {
701                 SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance started ");
702                 tts_client_use_callback(client);
703                 client->utt_started_cb(client->tts, client->utt_id, client->utt_started_user_data);
704                 tts_client_not_use_callback(client);
705         } else {
706                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started ");
707         }
708
709         return EINA_FALSE;
710 }
711
712 int __tts_cb_utt_started(int uid, int utt_id)
713 {
714         tts_client_s* client = tts_client_get_by_uid(uid);
715
716         if (NULL == client) {
717                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] A handle is not valid");
718                 return TTS_ERROR_INVALID_PARAMETER;
719         }
720
721         SLOG(LOG_DEBUG, TAG_TTSC, "utterance started : utt id(%d) ", utt_id);
722
723         client->utt_id = utt_id;
724
725         /* call callback function */
726         if (NULL != client->utt_started_cb) {
727                 ecore_timer_add(0, __tts_notify_utt_started, client->tts);
728         } else {
729                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started ");
730         }
731
732         return 0;
733 }
734
735 static Eina_Bool __tts_notify_utt_completed(void *data)
736 {
737         tts_h tts = (tts_h)data;
738
739         tts_client_s* client = tts_client_get(tts);
740
741         /* check handle */
742         if (NULL == client) {
743                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to notify utt completed : A handle is not valid");
744                 return EINA_FALSE;
745         }
746
747         if (NULL != client->utt_completeted_cb) {
748                 SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance completed ");
749                 tts_client_use_callback(client);
750                 client->utt_completeted_cb(client->tts, client->utt_id, client->utt_completed_user_data);
751                 tts_client_not_use_callback(client);
752         } else {
753                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance completed ");
754         }
755
756         return EINA_FALSE;
757 }
758
759 int __tts_cb_utt_completed(int uid, int utt_id)
760 {
761         tts_client_s* client = tts_client_get_by_uid(uid);
762
763         if (NULL == client) {
764                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] A handle is not valid");
765                 return TTS_ERROR_INVALID_PARAMETER;
766         }
767
768         SLOG(LOG_DEBUG, TAG_TTSC, "utterance completed : uttid(%d) ", utt_id);
769
770         client->utt_id = utt_id;
771
772         /* call callback function */
773         if (NULL != client->utt_completeted_cb) {
774                 ecore_timer_add(0, __tts_notify_utt_completed, client->tts);
775         } else {
776                 SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance completed ");
777         }
778
779         return 0;
780 }
781
782 int tts_set_state_changed_cb(tts_h tts, tts_state_changed_cb callback, void* user_data)
783 {
784         if (NULL == tts || NULL == callback) {
785                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set state changed cb : Input parameter is null");
786                 return TTS_ERROR_INVALID_PARAMETER;
787         }
788
789         tts_client_s* client = tts_client_get(tts);
790
791         if (NULL == client) {
792                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set state changed cb : A handle is not valid");
793                 return TTS_ERROR_INVALID_PARAMETER;
794         }
795
796         if (TTS_STATE_CREATED != client->current_state) {
797                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set state changed cb : Current state is not 'Created'."); 
798                 return TTS_ERROR_INVALID_STATE;
799         }
800
801         client->state_changed_cb = callback;
802         client->state_changed_user_data = user_data;
803
804         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set state changed cb");
805
806         return 0;
807 }
808
809 int tts_unset_state_changed_cb(tts_h tts)
810 {
811         if (NULL == tts) {
812                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset state changed cb : Input parameter is null");
813                 return TTS_ERROR_INVALID_PARAMETER;
814         }
815
816         tts_client_s* client = tts_client_get(tts);
817
818         if (NULL == client) {
819                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset state changed cb : A handle is not valid");
820                 return TTS_ERROR_INVALID_PARAMETER;
821         }
822
823         if (TTS_STATE_CREATED != client->current_state) {
824                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset state changed cb : Current state is not 'Created'."); 
825                 return TTS_ERROR_INVALID_STATE;
826         }
827
828         client->state_changed_cb = NULL;
829         client->state_changed_user_data = NULL;
830
831         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset state changed cb");
832
833         return 0;
834 }
835
836 int tts_set_utterance_started_cb(tts_h tts, tts_utterance_started_cb callback, void* user_data)
837 {
838         if (NULL == tts || NULL == callback) {
839                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt started cb : Input parameter is null");
840                 return TTS_ERROR_INVALID_PARAMETER;
841         }
842
843         tts_client_s* client = tts_client_get(tts);
844
845         if (NULL == client) {
846                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt started cb : A handle is not valid");
847                 return TTS_ERROR_INVALID_PARAMETER;
848         }
849
850         if (TTS_STATE_CREATED != client->current_state) {
851                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt started cb : Current state is not 'Created'."); 
852                 return TTS_ERROR_INVALID_STATE;
853         }
854
855         client->utt_started_cb = callback;
856         client->utt_started_user_data = user_data;
857
858         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set utt started cb");
859         
860         return 0;
861 }
862
863 int tts_unset_utterance_started_cb(tts_h tts)
864 {
865         if (NULL == tts) {
866                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : Input parameter is null");
867                 return TTS_ERROR_INVALID_PARAMETER;
868         }
869
870         tts_client_s* client = tts_client_get(tts);
871
872         if (NULL == client) {
873                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : A handle is not valid");
874                 return TTS_ERROR_INVALID_PARAMETER;
875         }
876
877         if (TTS_STATE_CREATED != client->current_state) {
878                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : Current state is not 'Created'."); 
879                 return TTS_ERROR_INVALID_STATE;
880         }
881
882         client->utt_started_cb = NULL;
883         client->utt_started_user_data = NULL;
884
885         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset utt started cb");
886         
887         return 0;
888 }
889
890 int tts_set_utterance_completed_cb(tts_h tts, tts_utterance_completed_cb callback, void* user_data)
891 {
892         if (NULL == tts || NULL == callback) {
893                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : Input parameter is null");
894                 return TTS_ERROR_INVALID_PARAMETER;
895         }
896
897         tts_client_s* client = tts_client_get(tts);
898
899         if (NULL == client) {
900                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : A handle is not valid");
901                 return TTS_ERROR_INVALID_PARAMETER;
902         }
903
904         if (TTS_STATE_CREATED != client->current_state) {
905                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : Current state is not 'Created'."); 
906                 return TTS_ERROR_INVALID_STATE;
907         }
908
909         client->utt_completeted_cb = callback;
910         client->utt_completed_user_data = user_data;
911
912         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set utt completed cb");
913         
914         return 0;
915 }
916
917 int tts_unset_utterance_completed_cb(tts_h tts)
918 {
919         if (NULL == tts) {
920                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : Input parameter is null");
921                 return TTS_ERROR_INVALID_PARAMETER;
922         }
923
924         tts_client_s* client = tts_client_get(tts);
925
926         if (NULL == client) {
927                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : A handle is not valid");
928                 return TTS_ERROR_INVALID_PARAMETER;
929         }
930
931         if (TTS_STATE_CREATED != client->current_state) {
932                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : Current state is not 'Created'."); 
933                 return TTS_ERROR_INVALID_STATE;
934         }
935
936         client->utt_completeted_cb = NULL;
937         client->utt_completed_user_data = NULL;
938
939         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset utt completed cb");
940         return 0;
941 }
942
943 int tts_set_error_cb(tts_h tts, tts_error_cb callback, void* user_data)
944 {
945         if (NULL == tts || NULL == callback) {
946                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : Input parameter is null");
947                 return TTS_ERROR_INVALID_PARAMETER;
948         }
949
950         tts_client_s* client = tts_client_get(tts);
951
952         if (NULL == client) {
953                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : A handle is not valid");
954                 return TTS_ERROR_INVALID_PARAMETER;
955         }
956
957         if (TTS_STATE_CREATED != client->current_state) {
958                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : Current state is not 'Created'."); 
959                 return TTS_ERROR_INVALID_STATE;
960         }
961
962         client->error_cb = callback;
963         client->error_user_data = user_data;
964
965         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set error cb");
966         
967         return 0;
968 }
969
970 int tts_unset_error_cb(tts_h tts)
971 {
972         if (NULL == tts) {
973                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : Input parameter is null");
974                 return TTS_ERROR_INVALID_PARAMETER;
975         }
976
977         tts_client_s* client = tts_client_get(tts);
978
979         if (NULL == client) {
980                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : A handle is not valid");
981                 return TTS_ERROR_INVALID_PARAMETER;
982         }
983         
984         if (TTS_STATE_CREATED != client->current_state) {
985                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : Current state is not 'Created'."); 
986                 return TTS_ERROR_INVALID_STATE;
987         }
988
989         client->error_cb = NULL;
990         client->error_user_data = NULL;
991
992         SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset error cb");
993
994         return 0;
995 }
996
997 int __get_cmd_line(char *file, char *buf) 
998 {
999         FILE *fp = NULL;
1000         int i;
1001
1002         fp = fopen(file, "r");
1003         if (fp == NULL) {
1004                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get command line");
1005                 return -1;
1006         }
1007
1008         memset(buf, 0, 256);
1009         fgets(buf, 256, fp);
1010         fclose(fp);
1011
1012         return 0;
1013 }
1014
1015 static bool _tts_is_alive()
1016 {
1017         DIR *dir;
1018         struct dirent *entry;
1019         struct stat filestat;
1020         
1021         int pid;
1022         char cmdLine[256];
1023         char tempPath[256];
1024
1025         dir  = opendir("/proc");
1026         if (NULL == dir) {
1027                 SLOG(LOG_ERROR, TAG_TTSC, "process checking is FAILED");
1028                 return FALSE;
1029         }
1030
1031         while ((entry = readdir(dir)) != NULL) {
1032                 if (0 != lstat(entry->d_name, &filestat))
1033                         continue;
1034
1035                 if (!S_ISDIR(filestat.st_mode))
1036                         continue;
1037
1038                 pid = atoi(entry->d_name);
1039                 if (pid <= 0) continue;
1040
1041                 sprintf(tempPath, "/proc/%d/cmdline", pid);
1042                 if (0 != __get_cmd_line(tempPath, cmdLine)) {
1043                         continue;
1044                 }
1045
1046                 if ( 0 == strncmp(cmdLine, "[tts-daemon]", strlen("[tts-daemon]")) ||
1047                         0 == strncmp(cmdLine, "tts-daemon", strlen("tts-daemon")) ||
1048                         0 == strncmp(cmdLine, "/usr/bin/tts-daemon", strlen("/usr/bin/tts-daemon"))) {
1049                                 SLOG(LOG_DEBUG, TAG_TTSC, "tts-daemon is ALIVE !!");
1050                                 closedir(dir);
1051                                 return TRUE;
1052                 }
1053         }
1054
1055         SLOG(LOG_DEBUG, TAG_TTSC, "THERE IS NO tts-daemon !!");
1056
1057         closedir(dir);
1058         return FALSE;
1059 }
1060
1061 static int __tts_check_tts_daemon()
1062 {
1063         if (TRUE == _tts_is_alive()) {
1064                 return 0;
1065         }
1066         
1067         /* fork-exec tts-daemom */
1068         int pid, i;
1069
1070         pid = fork();
1071
1072         switch(pid) {
1073         case -1:
1074                 SLOG(LOG_ERROR, TAG_TTSC, "Fail to create tts-daemon");
1075                 break;
1076
1077         case 0:
1078                 setsid();
1079                 for (i = 0;i < _NSIG;i++)
1080                         signal(i, SIG_DFL);
1081
1082                 execl("/usr/bin/tts-daemon", "/usr/bin/tts-daemon", NULL);
1083                 break;
1084
1085         default:
1086                 break;
1087         }
1088
1089         return 0;
1090 }