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