Fix focus and release issue in ttsd_player
[platform/core/uifw/tts.git] / server / ttsd_player.c
1 /*
2 *  Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14 #include <audio_io.h>
15 #include <Ecore.h>
16 #include <sound_manager.h>
17 #include <sound_manager_internal.h>
18
19 #include "ttsd_main.h"
20 #include "ttsd_player.h"
21 #include "ttsd_data.h"
22 #include "ttsd_dbus.h"
23
24 /*
25 * Internal data structure
26 */
27
28 typedef enum {
29         AUDIO_STATE_NONE = 0,
30         AUDIO_STATE_READY,
31         AUDIO_STATE_PLAY
32 } audio_state_e;
33
34 typedef struct {
35         int                     uid;    /** client id */
36         app_state_e             state;  /** client state */
37
38         /* Current utterance information */
39         ttse_result_event_e     event;  /** event of last utterance */
40
41         bool                    is_paused_data;
42         int                     idx;
43         sound_data_s*           paused_data;
44 } player_s;
45
46 #define SOUND_BUFFER_LENGTH     2048
47
48 /** player init info */
49 static bool g_player_init = false;
50
51 /** Client list */
52 static GList *g_player_list;
53
54 /** current player information */
55 static player_s* g_playing_info;
56
57 /* player state */
58 static audio_state_e g_audio_state;
59
60 static ttse_audio_type_e g_audio_type;
61
62 static int g_sampling_rate;
63
64 static audio_out_h g_audio_h;
65
66 static sound_stream_info_h g_stream_info_h;
67
68 /*
69 * Internal Interfaces
70 */
71
72 player_s* __player_get_item(int uid)
73 {
74         GList *iter = NULL;
75         player_s *data = NULL;
76
77         if (0 < g_list_length(g_player_list)) {
78                 /* Get a first item */
79                 iter = g_list_first(g_player_list);
80
81                 while (NULL != iter) {
82                         /* Get handle data from list */
83                         data = (player_s*)iter->data;
84
85                         /* compare uid */
86                         if (uid == data->uid)
87                                 return data;
88
89                         /* Get next item */
90                         iter = g_list_next(iter);
91                 }
92         }
93
94         return NULL;
95 }
96
97 void __player_focus_state_cb(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state,
98                                                         sound_stream_focus_change_reason_e reason_for_change, int sound_behavior, const char *extra_info, void *user_data)
99 {
100         SLOG(LOG_DEBUG, tts_tag(), "===== Focus state changed cb");
101
102         if (stream_info != g_stream_info_h) {
103                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Invalid stream info handle");
104                 return;
105         }
106         SLOG(LOG_WARN, tts_tag(), "[Player] focus state changed to (%d) with reason(%d)", (int)focus_state, (int)reason_for_change);
107
108         if (AUDIO_STATE_PLAY == g_audio_state && focus_mask == SOUND_STREAM_FOCUS_FOR_PLAYBACK && SOUND_STREAM_FOCUS_STATE_RELEASED == focus_state) {
109                 if (TTSD_MODE_DEFAULT == ttsd_get_mode()) {
110                         g_audio_state = AUDIO_STATE_READY;
111
112                         if (NULL == g_playing_info) {
113                                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player");
114                                 return;
115                         }
116
117                         if (APP_STATE_PLAYING == g_playing_info->state) {
118                                 int uid = g_playing_info->uid;
119
120                                 if (0 != ttsd_player_pause(uid)) {
121                                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to pause the player");
122                                         return;
123                                 }
124
125                                 g_playing_info->state = APP_STATE_PAUSED;
126                                 ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
127                                 int pid = ttsd_data_get_pid(uid);
128                                 /* send message to client about changing state */
129                                 ttsdc_send_set_state_message(pid, uid, APP_STATE_PAUSED);
130                         }
131                 } else {
132                         SLOG(LOG_DEBUG, tts_tag(), "[Player] Ignore focus state cb - mode(%d)", ttsd_get_mode());
133                 }
134         }
135
136         SLOG(LOG_DEBUG, tts_tag(), "=====");
137         SLOG(LOG_DEBUG, tts_tag(), "");
138
139         return;
140 }
141
142 static int __create_audio_out(ttse_audio_type_e type, int rate)
143 {
144         int ret = -1;
145         audio_sample_type_e sample_type;
146
147         if (TTSE_AUDIO_TYPE_RAW_S16 == type) {
148                 sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
149         } else {
150                 sample_type = AUDIO_SAMPLE_TYPE_U8;
151         }
152
153         ret = audio_out_create_new(rate, AUDIO_CHANNEL_MONO, sample_type, &g_audio_h);
154         if (AUDIO_IO_ERROR_NONE != ret) {
155                 g_audio_state = AUDIO_STATE_NONE;
156                 g_audio_h = NULL;
157                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio");
158                 return -1;
159         } else {
160                 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Create audio");
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, tts_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, tts_tag(), "[Player ERROR] Fail to destroy audio");
182                 return -1;
183         } else {
184                 SLOG(LOG_DEBUG, tts_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_ERROR, tts_tag(), "===== End thread");
199 }
200
201 static void __set_policy_for_playing(int volume)
202 {
203         /* Set stream info */
204         int ret;
205         if (TTSD_MODE_DEFAULT == ttsd_get_mode()) {
206                 ret = sound_manager_acquire_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
207                 if (SOUND_MANAGER_ERROR_NONE != ret) {
208                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to acquire focus");
209                 }
210         }
211         ret = audio_out_set_sound_stream_info(g_audio_h, g_stream_info_h);
212         if (AUDIO_IO_ERROR_NONE != ret) {
213                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to set stream info");
214         }
215
216         return;
217 }
218
219 static void __unset_policy_for_playing()
220 {
221         int ret;
222         /* Unset stream info */
223         if (TTSD_MODE_DEFAULT == ttsd_get_mode()) {
224                 sound_stream_focus_state_e state_for_playing = SOUND_STREAM_FOCUS_STATE_ACQUIRED;
225                 ret = sound_manager_get_focus_state(g_stream_info_h, &state_for_playing, NULL);
226                 if (SOUND_MANAGER_ERROR_NONE != ret) {
227                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to get focus state: %d", ret);
228                 }
229
230                 if (SOUND_STREAM_FOCUS_STATE_ACQUIRED == state_for_playing) {
231                         ret = sound_manager_release_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
232                         if (SOUND_MANAGER_ERROR_NONE != ret) {
233                                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to release focus");
234                         }
235                 }
236         }
237
238         return;
239 }
240
241 static void __play_thread(void *data, Ecore_Thread *thread)
242 {
243         SLOG(LOG_DEBUG, tts_tag(), "===== Start thread");
244
245         if (NULL == g_playing_info) {
246                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] No current player");
247                 return;
248         }
249
250         player_s* player = g_playing_info;
251         sound_data_s* sound_data = NULL;
252
253         int ret = -1;
254         int len = SOUND_BUFFER_LENGTH;
255         int idx = 0;
256
257         /* set volume policy as 40% */
258         __set_policy_for_playing(40);
259         while (1) {
260                 if (true == player->is_paused_data) {
261                         /* Resume player */
262                         sound_data = player->paused_data;
263                         player->paused_data = NULL;
264
265                         idx = player->idx;
266
267                         player->is_paused_data = false;
268                         player->idx = 0;
269
270                         if (NULL == sound_data) {
271                                 /* Request unprepare */
272                                 ret = audio_out_unprepare(g_audio_h);
273                                 if (AUDIO_IO_ERROR_NONE != ret) {
274                                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
275                                 } else {
276                                         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio");
277                                 }
278
279                                 g_audio_state = AUDIO_STATE_READY;
280
281                                 /* unset volume policy, volume will be 100% */
282                                 __unset_policy_for_playing();
283                                 return;
284                         }
285                         SLOG(LOG_INFO, tts_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)", 
286                                 sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event);
287                 } else {
288                         sound_data = NULL;
289                         ret = ttsd_data_get_sound_data(player->uid, &sound_data);
290                         if (0 != ret || NULL == sound_data) {
291                                 /* empty queue */
292                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] No sound data. Waiting mode");
293                                 /* release audio & recover session */
294                                 ret = audio_out_unprepare(g_audio_h);
295                                 if (AUDIO_IO_ERROR_NONE != ret) {
296                                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
297                                 } else {
298                                         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio");
299                                 }
300                                 g_audio_state = AUDIO_STATE_READY;
301
302                                 /* unset volume policy, volume will be 100% */
303                                 __unset_policy_for_playing();
304
305                                 /* wait for new audio data come */
306                                 while (1) {
307                                         usleep(10000);
308                                         if (NULL == g_playing_info) {
309                                                 /* current playing uid is replaced */
310                                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Finish thread");
311                                                 return;
312                                         } else if (0 < ttsd_data_get_sound_data_size(player->uid)) {
313                                                 /* new audio data come */
314                                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Resume thread");
315                                                 break;
316                                         }
317                                 }
318
319                                 /* set volume policy as 40%, when resume play thread*/
320                                 __set_policy_for_playing(40);
321
322                                 /* resume play thread */
323                                 player->state = APP_STATE_PLAYING;
324                                 continue;
325                         }
326
327                         /* If wdata's event is 'start', current wdata is first data of engine for synthesis.
328                          * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
329                          * When previous wdata's event is 'finish' and current wdata's event is 'finish',
330                          * the player should send utt started event.
331                          */
332                         if (TTSE_RESULT_EVENT_START == sound_data->event ||
333                            (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
334                                 int pid = ttsd_data_get_pid(player->uid);
335
336                                 if (pid <= 0) {
337                                         SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid");
338                                         /* unset volume policy, volume will be 100% */
339                                         __unset_policy_for_playing();
340                                         return;
341                                 }
342
343                                 if (0 != ttsdc_send_utt_start_message(pid, player->uid, sound_data->utt_id)) {
344                                         SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", 
345                                                 pid, player->uid, sound_data->utt_id);
346                                 }
347                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Start utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id);
348                         }
349
350                         /* Save last event to check utterance start */
351                         player->event = sound_data->event;
352                         idx = 0;
353
354                         if (NULL == sound_data->data || 0 >= sound_data->data_size) {
355                                 if (TTSE_RESULT_EVENT_FINISH == sound_data->event) {
356                                         SLOG(LOG_DEBUG, tts_tag(), "No sound data");
357                                         /* send utterence finish signal */
358                                         int pid = ttsd_data_get_pid(player->uid);
359
360                                         if (pid <= 0) {
361                                                 SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid");
362                                                 /* unset volume policy, volume will be 100% */
363                                                 __unset_policy_for_playing();
364                                                 return;
365                                         }
366                                         if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) {
367                                                 SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", 
368                                                         pid, player->uid, sound_data->utt_id);
369                                         }
370                                 }
371                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id);
372                                 continue;
373                         }
374                 }
375
376                 if (g_sampling_rate != sound_data->rate || g_audio_type != sound_data->audio_type) {
377                         SLOG(LOG_DEBUG, tts_tag(), "[Player] Change audio handle : org type(%d) org rate(%d)", g_audio_type, g_sampling_rate);
378                         if (NULL != g_audio_h) {
379                                 __destroy_audio_out();
380                         }
381
382                         if (0 > __create_audio_out(sound_data->audio_type, sound_data->rate)) {
383                                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out");
384                                 /* unset volume policy, volume will be 100% */
385                                 __unset_policy_for_playing();
386                                 return;
387                         }
388                         __set_policy_for_playing(40);
389                 }
390
391                 while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) {
392                         if ((unsigned int)idx >= sound_data->data_size)
393                                 break;
394
395                         if ((unsigned int)idx + SOUND_BUFFER_LENGTH > sound_data->data_size) {
396                                 len = sound_data->data_size - idx;
397                         } else {
398                                 len = SOUND_BUFFER_LENGTH;
399                         }
400
401                         if (AUDIO_STATE_READY == g_audio_state) {
402                                 /* Request prepare */
403                                 ret = audio_out_prepare(g_audio_h);
404                                 if (AUDIO_IO_ERROR_NONE != ret) {
405                                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to prepare audio : %d", ret);
406                                         g_playing_info = NULL;
407                                         /* unset volume policy, volume will be 100% */
408                                         __unset_policy_for_playing();
409                                         return;
410                                 }
411                                 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Prepare audio");
412                                 g_audio_state = AUDIO_STATE_PLAY;
413                         }
414
415                         char* temp_data = sound_data->data;
416                         ret = audio_out_write(g_audio_h, &temp_data[idx], len);
417                         if (0 > ret) {
418                                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to audio write - %d", ret);
419                         } else {
420                                 idx += len;
421                         }
422
423                         if (NULL == g_playing_info && APP_STATE_PAUSED != player->state) {
424                                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
425                                 g_audio_state = AUDIO_STATE_READY;
426                                 ret = audio_out_unprepare(g_audio_h);
427                                 if (AUDIO_IO_ERROR_NONE != ret) {
428                                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
429                                 }
430                                 /* unset volume policy, volume will be 100% */
431                                 __unset_policy_for_playing();
432
433                                 if (NULL != sound_data) {
434                                         if (NULL != sound_data->data) {
435                                                 free(sound_data->data);
436                                                 sound_data->data = NULL;
437                                         }
438
439                                         free(sound_data);
440                                         sound_data = NULL;
441                                 }
442
443                                 return;
444                         }
445
446                         if (APP_STATE_PAUSED == player->state) {
447                                 /* Save data */
448                                 player->paused_data = sound_data;
449
450                                 player->is_paused_data = true;
451                                 player->idx = idx;
452
453                                 g_audio_state = AUDIO_STATE_READY;
454                                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread by pause");
455
456                                 /* Request prepare */
457                                 ret = audio_out_unprepare(g_audio_h);
458                                 if (AUDIO_IO_ERROR_NONE != ret) {
459                                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
460                                 } else {
461                                         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio");
462                                 }
463                                 /* unset volume policy, volume will be 100% */
464                                 __unset_policy_for_playing();
465                                 return;
466                         }
467                 }
468
469                 if (NULL == g_playing_info && APP_STATE_READY == player->state) {
470                         /* player_stop */ 
471                         g_audio_state = AUDIO_STATE_READY;
472                         SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread");
473
474                         /* Request prepare */
475                         ret = audio_out_unprepare(g_audio_h);
476                         if (AUDIO_IO_ERROR_NONE != ret) {
477                                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
478                         } else {
479                                 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio");
480                         }
481
482                         if (NULL != sound_data) {
483                                 if (NULL != sound_data->data) {
484                                         free(sound_data->data);
485                                         sound_data->data = NULL;
486                                 }
487
488                                 free(sound_data);
489                                 sound_data = NULL;
490                         }
491                         /* unset volume policy, volume will be 100% */
492                         __unset_policy_for_playing();
493                         return;
494                 }
495
496                 if ((APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) &&
497                         (TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
498                         /* send utterence finish signal */
499                         int pid = ttsd_data_get_pid(player->uid);
500
501                         if (pid <= 0) {
502                                 SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid");
503                                 /* unset volume policy, volume will be 100% */
504                                 __unset_policy_for_playing();
505                                 return;
506                         }
507
508                         if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) {
509                                 SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", 
510                                         pid, player->uid, sound_data->utt_id);
511                                 /* unset volume policy, volume will be 100% */
512                                 __unset_policy_for_playing();
513                                 return;
514                         }
515
516                         SLOG(LOG_DEBUG, tts_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id);
517                 }
518
519                 if (NULL != sound_data) {
520                         if (NULL != sound_data->data) {
521                                 free(sound_data->data);
522                                 sound_data->data = NULL;
523                         }
524
525                         free(sound_data);
526                         sound_data = NULL;
527                 }
528
529                 if (NULL == g_playing_info) {
530                         SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
531                         g_audio_state = AUDIO_STATE_READY;
532                         ret = audio_out_unprepare(g_audio_h);
533                         if (AUDIO_IO_ERROR_NONE != ret) {
534                                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret);
535                         }
536                         /* unset volume policy, volume will be 100% */
537                         __unset_policy_for_playing();
538
539                         return;
540                 }
541         }
542 }
543
544 /*
545 * Player Interfaces
546 */
547 int ttsd_player_init()
548 {
549         g_playing_info = NULL;
550         g_audio_state = AUDIO_STATE_NONE;
551         g_audio_h = NULL;
552
553         int ret;
554
555         ecore_thread_max_set(1);
556
557         ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __player_focus_state_cb, NULL, &g_stream_info_h);
558         if (SOUND_MANAGER_ERROR_NONE != ret) {
559                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create stream info");
560                 return -1;
561         } else {
562                 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Create stream info");
563         }
564
565         ecore_thread_max_set(1);
566
567         ret = __create_audio_out(TTSE_AUDIO_TYPE_RAW_S16, 16000);
568         if (0 != ret)
569                 return -1;
570
571         g_player_init = true;
572
573         return 0;
574 }
575
576 int ttsd_player_release(void)
577 {
578         if (false == g_player_init) {
579                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
580                 return TTSD_ERROR_OPERATION_FAILED;
581         }
582
583         int ret;
584
585         SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] ==========================");
586         SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
587         SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] ==========================");
588
589         /* The thread should be released */
590         int thread_count = ecore_thread_active_get();
591         int count = 0;
592         while (0 < thread_count) {
593                 usleep(10000);
594
595                 count++;
596                 if (20 == count) {
597                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
598                         break;
599                 }
600
601                 thread_count = ecore_thread_active_get();
602         }
603
604         SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Thread is released");
605
606         ret = __destroy_audio_out();
607         if (0 != ret)
608                 return -1;
609
610         ret = sound_manager_destroy_stream_information(g_stream_info_h);
611         if (SOUND_MANAGER_ERROR_NONE != ret) {
612                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy stream info");
613         } else {
614                 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Destroy stream info");
615         }
616
617         /* clear g_player_list */
618         g_playing_info = NULL;
619         g_player_init = false;
620
621         return 0;
622 }
623
624 int ttsd_player_create_instance(int uid)
625 {
626         if (false == g_player_init) {
627                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
628                 return -1;
629         }
630
631         /* Check uid is duplicated */
632         if (NULL != __player_get_item(uid)) {
633                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is already registered", uid);
634                 return -1;
635         }
636
637         player_s* new_client = (player_s*)calloc(1, sizeof(player_s));
638         if (NULL == new_client) {
639                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to allocate memory");
640                 return TTSE_ERROR_OUT_OF_MEMORY;
641         }
642
643         new_client->uid = uid;
644         new_client->event = TTSE_RESULT_EVENT_FINISH;
645         new_client->state = APP_STATE_READY;
646         new_client->is_paused_data = false;
647         new_client->idx = 0;
648         new_client->paused_data = NULL;
649         
650         SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Player] Create player : uid(%d)", uid);
651
652         g_player_list = g_list_append(g_player_list, new_client);
653
654         return 0;
655 }
656
657 int ttsd_player_destroy_instance(int uid)
658 {
659         if (false == g_player_init) {
660                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
661                 return -1;
662         }
663
664         player_s* current;
665         current = __player_get_item(uid);
666         if (NULL == current) {
667                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid);
668                 return -1;
669         }
670
671         if (NULL != g_playing_info) {
672                 if (uid == g_playing_info->uid) {
673                         g_playing_info = NULL;
674                 }
675         }
676
677         GList *iter = NULL;
678         player_s *data = NULL;
679
680         if (0 < g_list_length(g_player_list)) {
681                 /* Get a first item */
682                 iter = g_list_first(g_player_list);
683
684                 while (NULL != iter) {
685                         /* Get handle data from list */
686                         data = (player_s*)iter->data;
687
688                         if (NULL != data) {
689                                 /* compare uid */
690                                 if (uid == data->uid) {
691                                         g_player_list = g_list_remove_link(g_player_list, iter);
692                                         free(data);
693                                         g_list_free(iter);              
694                                         break;
695                                 }
696                         }
697
698                         /* Get next item */
699                         iter = g_list_next(iter);
700                 }
701         }
702
703         SLOG(LOG_DEBUG, tts_tag(), "[PLAYER Success] Destroy instance");
704
705         return 0;
706 }
707
708 int ttsd_player_play(int uid)
709 {
710         if (false == g_player_init) {
711                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
712                 return -1;
713         }
714
715         if (NULL != g_playing_info) {
716                 if (uid == g_playing_info->uid) {
717                         SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%d) has already played", g_playing_info->uid);
718                         return 0;
719                 } else {
720                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%d)", g_playing_info->uid);
721                         ttsd_player_stop(g_playing_info->uid);
722                 }
723         }
724
725         SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%d)", uid);
726
727         /* Check sound queue size */
728         if (0 == ttsd_data_get_sound_data_size(uid)) {
729                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid);
730                 return -1;
731         }
732
733         /* Check uid */
734         player_s* current;
735         current = __player_get_item(uid);
736         if (NULL == current) {
737                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid);
738                 return -1;
739         }
740
741         current->state = APP_STATE_PLAYING;
742
743         g_playing_info = current;
744
745         SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
746
747         if (0 < ttsd_data_get_sound_data_size(current->uid)) {
748                 SLOG(LOG_DEBUG, tts_tag(), "[Player] Run thread");
749                 ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
750         }
751
752         return 0;
753 }
754
755 int ttsd_player_stop(int uid)
756 {
757         if (false == g_player_init) {
758                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
759                 return -1;
760         }
761
762         /* Check uid */
763         player_s* current;
764         current = __player_get_item(uid);
765         if (NULL == current) {
766                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid);
767                 return -1;
768         }
769
770         /* check whether uid is current playing or not */
771         if (NULL != g_playing_info) {
772                 if (uid == g_playing_info->uid) {
773                         /* release current playing info */
774                         g_playing_info = NULL;
775                 }
776         } else {
777                 SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
778         }
779
780         if (true == current->is_paused_data) {
781                 if (NULL != current->paused_data) {
782                         if (NULL != current->paused_data->data) {
783                                 free(current->paused_data->data);
784                                 current->paused_data->data = NULL;
785                         }
786
787                         free(current->paused_data);
788                         current->paused_data = NULL;
789                 }
790         }
791
792         current->event = TTSE_RESULT_EVENT_FINISH;
793         current->state = APP_STATE_READY;
794         current->is_paused_data = false;
795         current->idx = 0;
796
797         if (NULL == g_playing_info) {
798                 SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
799                 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
800                 SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
801
802                 /* The thread should be released */
803                 int thread_count = ecore_thread_active_get();
804                 int count = 0;
805                 while (0 < thread_count) {
806                         usleep(10000);
807
808                         count++;
809                         if (30 == count) {
810                                 SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
811                                 break;
812                         }
813
814                         thread_count = ecore_thread_active_get();
815                 }
816
817                 SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
818                 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
819                 SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
820         }
821
822         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid);
823
824         return 0;
825 }
826
827 int ttsd_player_clear(int uid)
828 {
829         if (false == g_player_init) {
830                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
831                 return -1;
832         }
833
834         /* Check uid */
835         player_s* current;
836         current = __player_get_item(uid);
837         if (NULL == current) {
838                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
839                 return -1;
840         }
841
842         if (true == current->is_paused_data) {
843                 if (NULL != current->paused_data) {
844                         if (NULL != current->paused_data->data) {
845                                 free(current->paused_data->data);
846                                 current->paused_data->data = NULL;
847                         }
848
849                         free(current->paused_data);
850                         current->paused_data = NULL;
851                 }
852         }
853
854         current->event = TTSE_RESULT_EVENT_FINISH;
855         current->state = APP_STATE_READY;
856         current->is_paused_data = false;
857         current->idx = 0;
858
859         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Clear player : uid(%d)", uid);
860
861         return 0;
862 }
863
864 int ttsd_player_pause(int uid)
865 {
866         SLOG(LOG_DEBUG, tts_tag(), "[Player] pause player : uid(%d)", uid);
867
868         if (false == g_player_init) {
869                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
870                 return -1;
871         }
872
873         /* Check uid */
874         player_s* current;
875         current = __player_get_item(uid);
876         if (NULL == current) {
877                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid);
878                 return -1;
879         }
880
881         /* check whether uid is current playing or not */
882         if (NULL != g_playing_info) {
883                 if (uid == g_playing_info->uid) {
884                         /* release current playing info */
885                         g_playing_info = NULL;
886                 } else {
887                         /* error case */
888                 }
889         }
890
891         current->state = APP_STATE_PAUSED;
892         
893         SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
894         SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
895         SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
896
897         /* The thread should be released */
898         int thread_count = ecore_thread_active_get();
899         int count = 0;
900         while (0 < thread_count) {
901                 usleep(10000);
902
903                 count++;
904                 if (30 == count) {
905                         SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
906                         break;
907                 }
908
909                 thread_count = ecore_thread_active_get();
910         }
911
912         SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
913         SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
914         SLOG(LOG_DEBUG, tts_tag(), "[Player] ==========================");
915
916         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Pause player : uid(%d)", uid);
917
918         return 0;
919 }
920
921 int ttsd_player_resume(int uid)
922 {
923         SLOG(LOG_DEBUG, tts_tag(), "[Player] Resume player : uid(%d)", uid);
924
925         if (false == g_player_init) {
926                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
927                 return -1;
928         }
929
930         /* Check id */
931         player_s* current;
932         current = __player_get_item(uid);
933         if (NULL == current) {
934                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid);
935                 return -1;
936         }
937
938         /* check current player */
939         if (NULL != g_playing_info)
940                 g_playing_info = NULL;
941
942         current->state = APP_STATE_PLAYING;
943         g_playing_info = current;
944
945         SLOG(LOG_DEBUG, tts_tag(), "[Player] Run thread");
946         ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
947
948         return 0;
949 }
950
951 int ttsd_player_all_stop()
952 {
953         if (false == g_player_init) {
954                 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
955                 return -1;
956         }
957
958         g_playing_info = NULL;
959
960         GList *iter = NULL;
961         player_s *data = NULL;
962
963         if (0 < g_list_length(g_player_list)) {
964                 /* Get a first item */
965                 iter = g_list_first(g_player_list);
966
967                 while (NULL != iter) {
968                         /* Get handle data from list */
969                         data = (player_s*)iter->data;
970
971                         app_state_e state;
972                         if (0 > ttsd_data_get_client_state(data->uid, &state)) {
973                                 SLOG(LOG_ERROR, tts_tag(), "[player ERROR] uid(%d) is not valid", data->uid);
974                                 ttsd_player_destroy_instance(data->uid);
975                                 iter = g_list_next(iter);
976                                 continue;
977                         }
978
979                         if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
980                                 data->event = TTSE_RESULT_EVENT_FINISH;
981                                 data->state = APP_STATE_READY;
982
983                                 if (true == data->is_paused_data) {
984                                         if (NULL != data->paused_data) {
985                                                 if (NULL != data->paused_data->data) {
986                                                         free(data->paused_data->data);
987                                                         data->paused_data->data = NULL;
988                                                 }
989
990                                                 free(data->paused_data);
991                                                 data->paused_data = NULL;
992                                         }
993                                 }
994
995                                 data->is_paused_data = false;
996                                 data->idx = 0;
997                         }
998
999                         /* Get next item */
1000                         iter = g_list_next(iter);
1001                 }
1002         }
1003
1004         SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!");
1005
1006         return 0;
1007 }