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