de4762f901987973d508c4ba3e1c365cfa8bbd05
[platform/core/uifw/tts.git] / server / ttsd_player.c
1 /*
2 *  Copyright (c) 2011-2014 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 #include <audio_io.h>
15 #include <Ecore.h>
16 #include <sound_manager.h>
17
18 #include "ttsd_main.h"
19 #include "ttsd_player.h"
20 #include "ttsd_data.h"
21 #include "ttsd_dbus.h"
22
23 /*
24 * Internal data structure
25 */
26
27 typedef enum {
28         AUDIO_STATE_NONE = 0,
29         AUDIO_STATE_READY,
30         AUDIO_STATE_PLAY
31 } audio_state_e;
32
33 typedef struct {
34         int                     uid;    /** client id */
35         app_state_e             state;  /** client state */
36
37         /* Current utterance information */
38         ttsp_result_event_e     event;  /** event of last utterance */
39
40         bool                    is_paused_data;
41         int                     idx;
42         sound_data_s            paused_data;
43 } player_s;
44
45 #define SOUND_BUFFER_LENGTH     2048
46
47 /** player init info */
48 static bool g_player_init = false;
49
50 /** Client list */
51 static GList *g_player_list;
52
53 /** current player information */
54 static player_s* g_playing_info;
55
56 /* player state */
57 static audio_state_e g_audio_state;
58
59 static ttsp_audio_type_e g_audio_type;
60
61 static int g_sampling_rate;
62
63 static audio_out_h g_audio_h;
64
65 /*
66 * Internal Interfaces
67 */
68
69 player_s* __player_get_item(int uid)
70 {
71         GList *iter = NULL;
72         player_s *data = NULL;
73
74         if (0 < g_list_length(g_player_list)) {
75                 /* Get a first item */
76                 iter = g_list_first(g_player_list);
77
78                 while (NULL != iter) {
79                         /* Get handle data from list */
80                         data = (player_s*)iter->data;
81
82                         /* compare uid */
83                         if (uid == data->uid)
84                                 return data;
85
86                         /* Get next item */
87                         iter = g_list_next(iter);
88                 }
89         }
90
91         return NULL;
92 }
93
94 void __player_audio_io_interrupted_cb(audio_io_interrupted_code_e code, void *user_data)
95 {
96         SLOG(LOG_DEBUG, get_tag(), "===== INTERRUPTED CALLBACK");
97
98         SLOG(LOG_WARN, get_tag(), "[Player] code : %d", (int)code);
99
100         g_audio_state = AUDIO_STATE_READY;
101
102         if (NULL == g_playing_info) {
103                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] No current player");
104                 return;
105         }
106
107         if (APP_STATE_PLAYING == g_playing_info->state) {
108                 g_playing_info->state = APP_STATE_PAUSED;
109
110                 ttsd_data_set_client_state(g_playing_info->uid, APP_STATE_PAUSED);
111
112                 int pid = ttsd_data_get_pid(g_playing_info->uid);
113
114                 /* send message to client about changing state */
115                 ttsdc_send_set_state_message(pid, g_playing_info->uid, APP_STATE_PAUSED);
116         }
117
118         SLOG(LOG_DEBUG, get_tag(), "=====");
119         SLOG(LOG_DEBUG, get_tag(), "  ");
120
121         return;
122 }
123
124 static int __create_audio_out(ttsp_audio_type_e type, int rate)
125 {
126         int ret = -1;
127         audio_sample_type_e sample_type;
128
129         if (TTSP_AUDIO_TYPE_RAW_S16 == type) {
130                 sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
131         } else {
132                 sample_type = AUDIO_SAMPLE_TYPE_U8;
133         }
134
135         ret = audio_out_create(rate, AUDIO_CHANNEL_MONO, sample_type, SOUND_TYPE_MEDIA, &g_audio_h);
136         if (AUDIO_IO_ERROR_NONE != ret) {
137                 g_audio_state = AUDIO_STATE_NONE;
138                 g_audio_h = NULL;
139                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to create audio");
140                 return -1;
141         } else {
142                 SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Create audio");
143         }
144
145         if (TTSD_MODE_DEFAULT != ttsd_get_mode()) {
146                 ret = audio_out_ignore_session(g_audio_h);
147                 if (AUDIO_IO_ERROR_NONE != ret) {
148                         g_audio_state = AUDIO_STATE_NONE;
149                         g_audio_h = NULL;
150                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to set ignore session");
151                         return -1;
152                 }
153         }
154
155         ret = audio_out_set_interrupted_cb(g_audio_h, __player_audio_io_interrupted_cb, NULL);
156         if (AUDIO_IO_ERROR_NONE != ret) {
157                 g_audio_state = AUDIO_STATE_NONE;
158                 g_audio_h = NULL;
159                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to set callback function");
160                 return -1;
161         }
162
163         g_audio_type = type;
164         g_sampling_rate = rate;
165
166         g_audio_state = AUDIO_STATE_READY;
167
168         return 0;
169 }
170
171 static int __destroy_audio_out()
172 {
173         if (NULL == g_audio_h) {
174                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Current handle is not valid");
175                 return -1;
176         }
177
178         int ret = -1;
179         ret = audio_out_destroy(g_audio_h);
180         if (AUDIO_IO_ERROR_NONE != ret) {
181                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to destroy audio");
182                 return -1;
183         } else {
184                 SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Destroy audio");
185         }
186
187         g_audio_type = 0;
188         g_sampling_rate = 0;
189
190         g_audio_state = AUDIO_STATE_NONE;
191         g_audio_h = NULL;
192
193         return 0;
194 }
195
196 static void __end_play_thread(void *data, Ecore_Thread *thread)
197 {
198         SLOG(LOG_DEBUG, get_tag(), "===== End thread");
199         return;
200 }
201
202 static void __play_thread(void *data, Ecore_Thread *thread)
203 {
204         SLOG(LOG_DEBUG, get_tag(), "===== Start thread");
205
206         if (NULL == g_playing_info) {
207                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] No current player");
208                 return;
209         }
210
211         player_s* player = g_playing_info;
212         sound_data_s wdata;
213
214         int ret = -1;
215         int len = SOUND_BUFFER_LENGTH;
216         int idx = 0;
217
218         while (1) {
219                 if (true == player->is_paused_data) {
220                         /* Resume player */
221                         wdata.data = player->paused_data.data;
222                         wdata.data_size = player->paused_data.data_size;
223                         wdata.utt_id = player->paused_data.utt_id;
224                         wdata.audio_type = player->paused_data.audio_type;
225                         wdata.rate = player->paused_data.rate;
226                         wdata.channels = player->paused_data.channels;
227                         wdata.event = player->paused_data.event;
228
229                         idx = player->idx;
230
231                         player->is_paused_data = false;
232                         player->idx = 0;
233                 } else {
234                         if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) {
235                                 g_playing_info = NULL;
236                                 SLOG(LOG_DEBUG, get_tag(), "[Player] No sound data. Finish thread");
237
238                                 /* Request unprepare */
239                                 ret = audio_out_unprepare(g_audio_h);
240                                 if (AUDIO_IO_ERROR_NONE != ret) {
241                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
242                                 } else {
243                                         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio");
244                                 }
245
246                                 g_audio_state = AUDIO_STATE_READY;
247                                 return;
248                         }
249
250                         /* If wdata's event is 'start', current wdata is first data of engine for synthesis.
251                          * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
252                          * When previous wdata's event is 'finish' and current wdata's event is 'finish',
253                          * the player should send utt started event.
254                          */
255                         if (TTSP_RESULT_EVENT_START == wdata.event ||
256                            (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) {
257                                 int pid = ttsd_data_get_pid(player->uid);
258
259                                 if (pid <= 0) {
260                                         SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid");
261                                         return;
262                                 }
263
264                                 if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) {
265                                         SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", 
266                                                 pid, player->uid, wdata.utt_id);
267                                 }
268                                 SLOG(LOG_DEBUG, get_tag(), "[Player] Start utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id);
269                         }
270
271                         /* Save last event to check utterance start */
272                         player->event = wdata.event;
273                         idx = 0;
274
275                         if (NULL == wdata.data || 0 >= wdata.data_size) {
276                                 if (TTSP_RESULT_EVENT_FINISH == wdata.event) {
277                                         SLOG(LOG_DEBUG, get_tag(), "No sound data");
278                                         /* send utterence finish signal */
279                                         int pid = ttsd_data_get_pid(player->uid);
280
281                                         if (pid <= 0) {
282                                                 SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid");
283                                                 return;
284                                         }
285                                         if (0 != ttsdc_send_utt_finish_message(pid, player->uid, wdata.utt_id)) {
286                                                 SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, player->uid, wdata.utt_id);
287                                         }
288                                 }
289                                 SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id);
290                                 continue;
291                         }
292                 }
293
294                 SLOG(LOG_DEBUG, get_tag(), "[Player] Sound info : id(%d) size(%d) audiotype(%d) rate(%d) event(%d)", 
295                         wdata.utt_id, wdata.data_size, wdata.audio_type, wdata.rate, wdata.event);
296
297                 if (g_sampling_rate != wdata.rate || g_audio_type != wdata.audio_type) {
298                         SLOG(LOG_DEBUG, get_tag(), "[Player] Change audio handle : org type(%d) org rate(%d)", g_audio_type, g_sampling_rate);
299                         if (NULL != g_audio_h) {
300                                 __destroy_audio_out();
301                         }
302
303                         if (0 > __create_audio_out(wdata.audio_type, wdata.rate)) {
304                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to create audio out");
305                                 return;
306                         }
307                 }
308
309                 while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) {
310                         if ((unsigned int)idx >= wdata.data_size)
311                                 break;
312
313                         if ((unsigned int)idx + SOUND_BUFFER_LENGTH > wdata.data_size) {
314                                 len = wdata.data_size - idx;
315                         } else {
316                                 len = SOUND_BUFFER_LENGTH;
317                         }
318
319                         if (AUDIO_STATE_READY == g_audio_state) {
320                                 /* Request prepare */
321                                 ret = audio_out_prepare(g_audio_h);
322                                 if (AUDIO_IO_ERROR_NONE != ret) {
323                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to prepare audio : %d", ret);
324                                         g_playing_info = NULL;
325                                         return;
326                                 }
327                                 SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Prepare audio");
328                                 g_audio_state = AUDIO_STATE_PLAY;
329                         }
330
331                         char* temp_data = wdata.data;
332                         ret = audio_out_write(g_audio_h, &temp_data[idx], len);
333                         if (0 > ret) {
334                                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Fail to audio write - %d", ret);
335                         } else {
336                                 idx += len;
337                         }
338
339                         if (APP_STATE_PAUSED == player->state) {
340                                 /* Save data */
341                                 player->paused_data.data = wdata.data;
342                                 player->paused_data.data_size = wdata.data_size;
343                                 player->paused_data.utt_id = wdata.utt_id;
344                                 player->paused_data.audio_type = wdata.audio_type;
345                                 player->paused_data.rate = wdata.rate;
346                                 player->paused_data.channels = wdata.channels;
347                                 player->paused_data.event = wdata.event;
348
349                                 player->is_paused_data = true;
350                                 player->idx = idx;
351
352                                 g_audio_state = AUDIO_STATE_READY;
353                                 SLOG(LOG_DEBUG, get_tag(), "[Player] Stop player thread by pause");
354
355                                 /* Request prepare */
356                                 ret = audio_out_unprepare(g_audio_h);
357                                 if (AUDIO_IO_ERROR_NONE != ret) {
358                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
359                                 } else {
360                                         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio");
361                                 }
362                                 return;
363                         }
364                 }
365
366                 if (NULL != wdata.data) {
367                         free(wdata.data);
368                         wdata.data = NULL;
369                 }
370
371                 if (APP_STATE_READY == player->state) {
372                         g_audio_state = AUDIO_STATE_READY;
373                         SLOG(LOG_DEBUG, get_tag(), "[Player] Stop player thread");
374
375                         /* Request prepare */
376                         ret = audio_out_unprepare(g_audio_h);
377                         if (AUDIO_IO_ERROR_NONE != ret) {
378                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
379                         } else {
380                                 SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio");
381                         }
382                         return;
383                 }
384
385                 if (TTSP_RESULT_EVENT_FINISH == wdata.event) {
386                         /* send utterence finish signal */
387                         int pid = ttsd_data_get_pid(player->uid);
388
389                         if (pid <= 0) {
390                                 SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid");
391                                 return;
392                         }
393
394                         if (0 != ttsdc_send_utt_finish_message(pid, player->uid, wdata.utt_id)) {
395                                 SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", 
396                                         pid, player->uid, wdata.utt_id);
397                                 return;
398                         }
399
400                         SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id);
401                 }
402         }
403 }
404
405 /*
406 * Player Interfaces
407 */
408 int ttsd_player_init()
409 {
410         g_playing_info = NULL;
411         g_audio_state = AUDIO_STATE_NONE;
412         g_audio_h = NULL;
413
414         int ret;
415
416         if (TTSD_MODE_DEFAULT == ttsd_get_mode()) {
417                 ret = sound_manager_set_session_type(SOUND_SESSION_TYPE_MEDIA);
418                 if (0 != ret) {
419                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to set session type");
420                 }
421
422                 ret = sound_manager_set_media_session_option(SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START, SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY);
423                 if (0 != ret) {
424                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail set media session option");
425                 } else {
426                         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] set media session option");
427                 }
428         }
429
430         ecore_thread_max_set(1);
431
432         ret = __create_audio_out(TTSP_AUDIO_TYPE_RAW_S16, 16000);
433         if (0 != ret)
434                 return -1;
435
436         g_player_init = true;
437
438         return 0;
439 }
440
441 int ttsd_player_release(void)
442 {
443         if (false == g_player_init) {
444                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
445                 return TTSD_ERROR_OPERATION_FAILED;
446         }
447
448         int ret;
449
450         ret = __destroy_audio_out();
451         if (0 != ret)
452                 return -1;
453
454         SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] ==========================");
455         SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
456         SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] ==========================");
457
458         /* The thread should be released */
459         int thread_count = ecore_thread_active_get();
460         int count = 0;
461         while (0 < thread_count) {
462                 usleep(10000);
463
464                 count++;
465                 if (100 == count) {
466                         SLOG(LOG_WARN, get_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
467                         break;
468                 }
469
470                 thread_count = ecore_thread_active_get();
471         }
472
473         SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] Thread is released");
474
475         /* clear g_player_list */
476         g_playing_info = NULL;
477         g_player_init = false;
478
479         return 0;
480 }
481
482 int ttsd_player_create_instance(int uid)
483 {
484         if (false == g_player_init) {
485                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
486                 return -1;
487         }
488
489         /* Check uid is duplicated */
490         if (NULL != __player_get_item(uid)) {
491                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is already registered", uid);
492                 return -1;
493         }
494
495         player_s* new_client = (player_s*)calloc(1, sizeof(player_s));
496
497         new_client->uid = uid;
498         new_client->event = TTSP_RESULT_EVENT_FINISH;
499         new_client->state = APP_STATE_READY;
500         new_client->is_paused_data = false;
501         new_client->idx = 0;
502         new_client->paused_data.data = NULL;
503
504         SLOG(LOG_DEBUG, get_tag(), "[Player] Create player : uid(%d)", uid);
505
506         g_player_list = g_list_append(g_player_list, new_client);
507
508         return 0;
509 }
510
511 int ttsd_player_destroy_instance(int uid)
512 {
513         if (false == g_player_init) {
514                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
515                 return -1;
516         }
517
518         player_s* current;
519         current = __player_get_item(uid);
520         if (NULL == current) {
521                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid);
522                 return -1;
523         }
524
525         if (NULL != g_playing_info) {
526                 if (uid == g_playing_info->uid) {
527                         g_playing_info = NULL;
528                 }
529         }
530
531         GList *iter = NULL;
532         player_s *data = NULL;
533
534         if (0 < g_list_length(g_player_list)) {
535                 /* Get a first item */
536                 iter = g_list_first(g_player_list);
537
538                 while (NULL != iter) {
539                         /* Get handle data from list */
540                         data = (player_s*)iter->data;
541
542                         if (NULL != data) {
543                                 /* compare uid */
544                                 if (uid == data->uid) {
545                                         g_player_list = g_list_remove_link(g_player_list, iter);
546                                         free(data);
547                                         break;
548                                 }
549                         }
550
551                         /* Get next item */
552                         iter = g_list_next(iter);
553                 }
554         }
555
556         SLOG(LOG_DEBUG, get_tag(), "[PLAYER Success] Destroy instance");
557
558         return 0;
559 }
560
561 int ttsd_player_play(int uid)
562 {
563         if (false == g_player_init) {
564                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
565                 return -1;
566         }
567
568         if (NULL != g_playing_info) {
569                 if (uid == g_playing_info->uid) {
570                         SLOG(LOG_DEBUG, get_tag(), "[Player] uid(%d) has already played", g_playing_info->uid);
571                         return 0;
572                 }
573         }
574
575         SLOG(LOG_DEBUG, get_tag(), "[Player] start play : uid(%d)", uid);
576
577         /* Check sound queue size */
578         if (0 == ttsd_data_get_sound_data_size(uid)) {
579                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid);
580                 return -1;
581         }
582
583         /* Check uid */
584         player_s* current;
585         current = __player_get_item(uid);
586         if (NULL == current) {
587                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid);
588                 return -1;
589         }
590
591         current->state = APP_STATE_PLAYING;
592
593         g_playing_info = current;
594
595         SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
596
597         if (0 < ttsd_data_get_sound_data_size(current->uid)) {
598                 SLOG(LOG_DEBUG, get_tag(), "[Player] Run thread");
599                 ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
600         }
601
602         return 0;
603 }
604
605 int ttsd_player_stop(int uid)
606 {
607         if (false == g_player_init) {
608                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
609                 return -1;
610         }
611
612         /* Check uid */
613         player_s* current;
614         current = __player_get_item(uid);
615         if (NULL == current) {
616                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid);
617                 return -1;
618         }
619
620         /* check whether uid is current playing or not */
621         if (NULL != g_playing_info) {
622                 if (uid == g_playing_info->uid) {
623                         /* release current playing info */
624                         g_playing_info = NULL;
625                 }
626         } else {
627                 SLOG(LOG_DEBUG, get_tag(), "[Player] No current playing");
628         }
629
630         if (true == current->is_paused_data) {
631                 if (NULL != current->paused_data.data) {
632                         free(current->paused_data.data);
633                         current->paused_data.data = NULL;
634                 }
635         }
636
637         current->event = TTSP_RESULT_EVENT_FINISH;
638         current->state = APP_STATE_READY;
639         current->is_paused_data = false;
640         current->idx = 0;
641
642         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid);
643
644         return 0;
645 }
646
647 int ttsd_player_pause(int uid)
648 {
649         SLOG(LOG_DEBUG, get_tag(), "[Player] pause player : uid(%d)", uid);
650
651         if (false == g_player_init) {
652                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
653                 return -1;
654         }
655
656         /* Check uid */
657         player_s* current;
658         current = __player_get_item(uid);
659         if (NULL == current) {
660                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid);
661                 return -1;
662         }
663
664         /* check whether uid is current playing or not */
665         if (NULL != g_playing_info) {
666                 if (uid == g_playing_info->uid) {
667                         /* release current playing info */
668                         g_playing_info = NULL;
669                 } else {
670                         /* error case */
671                 }
672         }
673
674         current->state = APP_STATE_PAUSED;
675
676         return 0;
677 }
678
679 int ttsd_player_resume(int uid)
680 {
681         SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player : uid(%d)", uid);
682
683         if (false == g_player_init) {
684                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
685                 return -1;
686         }
687
688         /* Check id */
689         player_s* current;
690         current = __player_get_item(uid);
691         if (NULL == current) {
692                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid);
693                 return -1;
694         }
695
696         /* check current player */
697         if (NULL != g_playing_info)
698                 g_playing_info = NULL;
699
700         current->state = APP_STATE_PLAYING;
701         g_playing_info = current;
702
703         SLOG(LOG_DEBUG, get_tag(), "[Player] Run thread");
704         ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
705
706         return 0;
707 }
708
709 int ttsd_player_all_stop()
710 {
711         if (false == g_player_init) {
712                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
713                 return -1;
714         }
715
716         g_playing_info = NULL;
717
718         GList *iter = NULL;
719         player_s *data = NULL;
720
721         if (0 < g_list_length(g_player_list)) {
722                 /* Get a first item */
723                 iter = g_list_first(g_player_list);
724
725                 while (NULL != iter) {
726                         /* Get handle data from list */
727                         data = (player_s*)iter->data;
728
729                         app_state_e state;
730                         if (0 > ttsd_data_get_client_state(data->uid, &state)) {
731                                 SLOG(LOG_ERROR, get_tag(), "[player ERROR] uid(%d) is not valid", data->uid);
732                                 ttsd_player_destroy_instance(data->uid);
733                                 iter = g_list_next(iter);
734                                 continue;
735                         }
736
737                         if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
738                                 data->event = TTSP_RESULT_EVENT_FINISH;
739                                 data->state = APP_STATE_READY;
740
741                                 if (true == data->is_paused_data) {
742                                         if (NULL != data->paused_data.data) {
743                                                 free(data->paused_data.data);
744                                                 data->paused_data.data = NULL;
745                                         }
746                                 }
747
748                                 data->is_paused_data = false;
749                                 data->idx = 0;
750                         }
751
752                         /* Get next item */
753                         iter = g_list_next(iter);
754                 }
755         }
756
757         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] player all stop!!");
758
759         return 0;
760 }