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.
17 #include "ttsd_main.h"
18 #include "ttsd_player.h"
19 #include "ttsd_data.h"
20 #include "ttsd_dbus.h"
23 #include "BackgroundVolume.h"
24 #include "AudioStream.h"
26 #include "tts_internal.h"
27 #include "ttsd_server.h"
30 * Internal data structure
34 unsigned int uid; /** client id */
36 /* Current utterance information */
37 ttse_result_event_e event; /** event of last utterance */
40 #define SOUND_BUFFER_LENGTH 2048
42 static const intptr_t CHECK_TIMER_DELETE = 1;
43 static const int EXTRA_INFO_LENGTH = 20;
45 /* Sound buf save for test */
51 static char g_temp_file_name[128] = {'\0',};
53 static int g_count = 0;
54 static pthread_mutex_t g_buf_save_mutex = PTHREAD_MUTEX_INITIALIZER;
57 /** player init info */
58 static bool g_player_init = false;
61 static GList *g_player_list;
63 /** current player information */
64 static player_s* g_playing_info;
66 static bool g_is_set_policy;
69 If you change this constant value. Please check the function '__set_timer_for_delay_recover()'.
70 If you choose too big value, it may cause integer overflow issue.
72 #define SND_MGR_DUCKING_DURATION 500
74 static pthread_mutex_t g_play_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
75 static pthread_mutex_t g_player_control_mutex = PTHREAD_MUTEX_INITIALIZER;
77 static pthread_cond_t g_play_thread_cond = PTHREAD_COND_INITIALIZER;
79 static BackgroundVolume* g_background_volume = nullptr;
80 static AudioStream* g_audio_stream = nullptr;
85 static void __set_playing_status(bool is_playing)
87 int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, is_playing ? 1 : 0);
88 SLOG(LOG_INFO, tts_tag(), "[Player] Set playing status (%s). ret(%d)", is_playing ? "True" : "False", ret);
92 static void __open_buffer_dump_file()
94 pthread_mutex_lock(&g_buf_save_mutex);
96 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is already opened(%s)", g_temp_file_name);
97 pthread_mutex_unlock(&g_buf_save_mutex);
103 snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/tts_temp_%d_%d", getpid(), g_count);
104 int ret = access(g_temp_file_name, 0);
107 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File is already exist");
108 if (0 == remove(g_temp_file_name)) {
109 SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Remove file");
119 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Temp file name=[%s]", g_temp_file_name);
122 g_pFile = fopen(g_temp_file_name, "wb+x");
123 if (NULL == g_pFile) {
124 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File not found!");
127 pthread_mutex_unlock(&g_buf_save_mutex);
130 static void __close_buffer_dump_file()
132 pthread_mutex_lock(&g_buf_save_mutex);
139 pthread_mutex_unlock(&g_buf_save_mutex);
142 static void __write_buffer_dump_file(const void* buffer, size_t length)
144 pthread_mutex_lock(&g_buf_save_mutex);
147 size_t ret = fwrite(buffer, 1, length, g_pFile);
148 SLOG(LOG_DEBUG, tts_tag(), "[Buffer Dump] Stored size(%zu / %zu)", ret, length);
150 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is not opened. Please check the file open");
153 pthread_mutex_unlock(&g_buf_save_mutex);
157 static bool __is_player_valid(player_s* player)
159 if (NULL == player || NULL == g_playing_info) {
160 SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is NULL");
164 if (g_playing_info != player || g_playing_info->uid != player->uid) {
165 SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is not current player");
172 player_s* __player_get_item(unsigned int uid)
175 player_s *data = NULL;
177 if (0 < g_list_length(g_player_list)) {
178 /* Get a first item */
179 iter = g_list_first(g_player_list);
181 while (NULL != iter) {
182 /* Get handle data from list */
183 data = (player_s*)iter->data;
186 if (uid == data->uid)
190 iter = g_list_next(iter);
197 static void __focus_release_callback()
199 if (NULL == g_playing_info) {
200 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player");
204 if (APP_STATE_PLAYING != ttsd_data_get_client_state(g_playing_info->uid)) {
208 unsigned int uid = g_playing_info->uid;
209 ttsd_mode_e mode = ttsd_data_get_mode(uid);
212 case TTSD_MODE_DEFAULT:
214 SLOG(LOG_DEBUG, tts_tag(), "[Player] Pause current player - mode(%d)", mode);
215 if (0 != ttsd_player_pause(uid)) {
216 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to pause the player");
220 ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
221 int pid = ttsd_data_get_pid(uid);
223 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to get pid. uid(%u)", uid);
225 /* send message to client about changing state */
226 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Player paused. pid(%d), uid(%u)", pid, uid);
227 ttsdc_ipc_send_set_state_message(pid, uid, APP_STATE_PAUSED);
232 case TTSD_MODE_NOTIFICATION:
233 case TTSD_MODE_SCREEN_READER:
235 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop current player - mode(%d)", mode);
236 ttsd_send_all_stop();
240 case TTSD_MODE_INTERRUPT:
241 SLOG(LOG_DEBUG, tts_tag(), "[Player] Ignore focus release - mode(%d)", mode);
245 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Invalid mode - mode(%d)", mode);
249 SLOG(LOG_DEBUG, tts_tag(), "@@@");
254 static void __end_play_thread(void *data, Ecore_Thread *thread)
256 SLOG(LOG_ERROR, tts_tag(), "@@@ End thread");
259 static void __set_policy_for_playing(void)
261 const char* extra_info = NULL;
262 if (TTSD_MODE_INTERRUPT == ttsd_get_mode()) {
263 extra_info = "TTSD_MODE_INTERRUPT";
266 g_audio_stream->acquireSoundFocus(extra_info);
267 g_background_volume->applyVolumeRatio();
268 g_is_set_policy = true;
269 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
270 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] set policy for playing");
275 static void __unset_policy_for_playing()
277 g_audio_stream->releaseSoundFocus();
278 g_background_volume->recoverVolumeRatio();
279 g_is_set_policy = false;
280 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
281 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] unset policy for playing");
286 static bool __does_interrupt_have_focus(sound_stream_focus_change_reason_e reason, int sound_behavior, char *extra_info)
288 SLOG(LOG_DEBUG, tts_tag(), "[Player] current Playback focus: extra_info(%s), reason(%d), sound_behavior(%d)", extra_info, reason, sound_behavior);
289 if (SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION != reason) {
293 if (NULL == extra_info || 0 >= strlen(extra_info) || 0 != strncmp(extra_info, "TTSD_MODE_INTERRUPT", EXTRA_INFO_LENGTH)) {
300 bool ttsd_player_does_interrupt_have_playback_focus()
302 sound_stream_focus_change_reason_e reason;
303 int sound_behavior = 0;
304 char *extra_info = NULL;
305 if (SOUND_MANAGER_ERROR_NONE != sound_manager_get_current_playback_focus(&reason, &sound_behavior, &extra_info)) {
306 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to get focus information");
310 bool result = __does_interrupt_have_focus(reason, sound_behavior, extra_info);
315 static int __notify_utterance_started_event(unsigned int uid, int utt_id)
317 int pid = ttsd_data_get_pid(uid);
319 SLOG(LOG_ERROR, tts_tag(), "[Player] Current player is not valid. uid(%u)", uid);
320 return TTSD_ERROR_INVALID_PARAMETER;
324 __open_buffer_dump_file();
326 __set_playing_status(true);
328 if (0 != ttsdc_ipc_send_utt_start_message(pid, uid, utt_id)) {
329 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to send Utterance Started Signal : pid(%d), uid(%u), utt_id(%d)",
331 return TTSD_ERROR_OPERATION_FAILED;
334 SLOG(LOG_INFO, tts_tag(), "[Player] Start utterance : uid(%u), utt_id(%d)", uid, utt_id);
335 return TTSD_ERROR_NONE;
338 static int __notify_utterance_completed_event(unsigned int uid, int utt_id)
340 int pid = ttsd_data_get_pid(uid);
342 SLOG(LOG_ERROR, tts_tag(), "[Player] Current player is not valid. uid(%u)", uid);
343 return TTSD_ERROR_INVALID_PARAMETER;
347 __close_buffer_dump_file();
349 __set_playing_status(false);
351 if (0 != ttsdc_ipc_send_utt_finish_message(pid, uid, utt_id)) {
352 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%u), utt_id(%d)",
354 return TTSD_ERROR_OPERATION_FAILED;
357 SLOG(LOG_INFO, tts_tag(), "[Player] Complete utterance : uid(%u), utt_id(%d)", uid, utt_id);
358 return TTSD_ERROR_NONE;
361 static int __play_sound_data(player_s* player, sound_data_s* sound_data)
363 if (TTSD_ERROR_NONE != g_audio_stream->setAudioFormat(sound_data->audio_type, sound_data->rate)) {
364 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out");
365 return TTSD_ERROR_OPERATION_FAILED;
368 // Check whether set_policy is done or not
369 if (false == g_is_set_policy) {
370 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Set policy");
371 __set_policy_for_playing();
374 if (TTSD_ERROR_NONE != g_audio_stream->prepareAudioOut()) {
375 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to prepare audio");
376 return TTSD_ERROR_OPERATION_FAILED;
379 unsigned int idx = sound_data->played_data_size;
380 while (idx < sound_data->data_size) {
381 app_tts_state_e state = ttsd_data_get_client_state(player->uid);
382 if (APP_STATE_PLAYING != state && APP_STATE_PAUSED != state) {
386 unsigned int len = 0;
387 if (idx + SOUND_BUFFER_LENGTH > sound_data->data_size) {
388 len = sound_data->data_size - idx;
390 len = SOUND_BUFFER_LENGTH;
393 char* temp_data = sound_data->data;
394 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Before audio_out_write. data(%p), data[%d](%p), uid(%u), utt_id(%d), len(%u)",
395 temp_data, idx, &temp_data[idx], player->uid, sound_data->utt_id, len);
398 __write_buffer_dump_file(&temp_data[idx], len);
401 if (TTSD_ERROR_NONE != g_audio_stream->playAudioData(&temp_data[idx], len)) {
402 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to write audio");
405 sound_data->played_data_size = idx;
406 SLOG(LOG_INFO, tts_tag(), "[Player INFO] After audio_out_write");
409 if (APP_STATE_PAUSED == state) {
410 return TTSD_ERROR_INVALID_STATE;
413 if (false == __is_player_valid(player)) {
414 return TTSD_ERROR_OPERATION_FAILED;
418 return TTSD_ERROR_NONE;
421 static void __play_thread_old(void *data, Ecore_Thread *thread)
423 SLOG(LOG_DEBUG, tts_tag(), "@@@ Start thread");
425 if (NULL == g_playing_info) {
426 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] No current player");
430 player_s* player = g_playing_info;
431 sound_data_s* sound_data = NULL;
435 /* set volume policy as 40% */
436 __set_policy_for_playing();
437 while (1) { // 1st while(1)
438 /* check g_playing_info one more time */
439 if (false == __is_player_valid(player)) {
440 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Player is not valid");
441 g_audio_stream->unprepareAudioOut();
442 __unset_policy_for_playing();
446 if (ttsd_data_is_paused_data_existing(player->uid)) {
448 sound_data = ttsd_data_get_first_sound_data(player->uid);
449 ttsd_data_set_paused_data_existing(player->uid, false);
451 if (NULL == sound_data) {
452 /* Request unprepare */
453 g_audio_stream->unprepareAudioOut();
455 /* unset volume policy, volume will be 100% */
456 __unset_policy_for_playing();
459 __set_playing_status(true);
461 SLOG(LOG_INFO, tts_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)",
462 sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event);
463 } else { // NO player->is_paused_data
464 sound_data = ttsd_data_get_first_sound_data(player->uid);
465 if (nullptr == sound_data) {
467 SLOG(LOG_ERROR, tts_tag(), "[Player] No sound data. Waiting mode");
469 /* wait for new audio data come */
470 while (1) { // 2nd while(1)
472 if (false == __is_player_valid(player)) {
473 /* current playing uid is replaced */
474 SLOG(LOG_INFO, tts_tag(), "[Player] Finish thread");
475 if (AudioStream::AUDIO_STATE_PLAY == g_audio_stream->getState()) {
476 /* release audio & recover session */
477 g_audio_stream->unprepareAudioOut();
479 /* unset volume policy, volume will be 100% */
480 __unset_policy_for_playing();
482 } else if (0 < ttsd_data_get_sound_data_size(player->uid)) {
483 /* new audio data come */
484 SLOG(LOG_INFO, tts_tag(), "[Player] Resume thread");
485 break; // exit from 2nd while(1)
488 /* If engine is not on processing */
489 ttsd_synthesis_control_e synth_control = ttsd_get_synth_control();
490 if (TTSD_SYNTHESIS_CONTROL_DOING != synth_control) {
491 SLOG(LOG_INFO, tts_tag(), "[Server INFO] synth_control(%d)", synth_control);
492 if (AudioStream::AUDIO_STATE_PLAY == g_audio_stream->getState()) {
493 /* release audio & recover session */
494 g_audio_stream->unprepareAudioOut();
496 /* unset volume policy, volume will be 100% */
497 __unset_policy_for_playing();
500 } // end of 2nd while(1). waiting for new audio data come
502 SLOG(LOG_INFO, tts_tag(), "[Player] Finish to wait for new audio data come");
504 if (AudioStream::AUDIO_STATE_READY == g_audio_stream->getState() || AudioStream::AUDIO_STATE_WAIT_FOR_PLAYING == g_audio_stream->getState()) {
505 /* set volume policy as 40%, when resume play thread*/
506 __set_policy_for_playing();
510 } // NULL == sound_data
512 /* If wdata's event is 'start', current wdata is first data of engine for synthesis.
513 * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
514 * When previous wdata's event is 'finish' and current wdata's event is 'finish',
515 * the player should send utt started event.
517 if (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
518 int ret = __notify_utterance_started_event(player->uid, sound_data->utt_id);
519 if (TTSD_ERROR_INVALID_PARAMETER == ret) {
520 g_audio_stream->unprepareAudioOut();
521 __unset_policy_for_playing();
524 } // (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event))
526 /* Save last event to check utterance start */
527 player->event = sound_data->event;
529 if (NULL == sound_data->data || 0 >= sound_data->data_size) {
530 ttse_result_event_e event = sound_data->event;
531 int utt_id = sound_data->utt_id;
533 if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(player->uid)) {
534 ttsd_data_destroy_sound_data(sound_data);
536 sound_data = nullptr;
538 if (TTSE_RESULT_EVENT_FINISH == event) {
539 SLOG(LOG_DEBUG, tts_tag(), "No sound data");
540 __unset_policy_for_playing();
542 ret = __notify_utterance_completed_event(player->uid, utt_id);
543 if (TTSD_ERROR_INVALID_PARAMETER == ret) {
544 g_audio_stream->unprepareAudioOut();
547 } // TTSE_RESULT_EVENT_FINISH == event
548 SLOG(LOG_INFO, tts_tag(), "[Player] Event(%d) utterance : uid(%u), uttid(%d)", event, player->uid, utt_id);
550 } // (NULL == sound_data->data || 0 >= sound_data->data_size)
551 } // NO player->is_paused_data
553 ret = __play_sound_data(player, sound_data);
554 if (TTSD_ERROR_INVALID_STATE == ret) {
555 SLOG(LOG_DEBUG, tts_tag(), "[Player] Player(%p) is paused, uid(%u)", player, player->uid);
556 ttsd_data_set_paused_data_existing(player->uid, true);
557 g_audio_stream->unprepareAudioOut();
558 __unset_policy_for_playing();
560 } else if (TTSD_ERROR_NONE != ret) {
561 SLOG(LOG_ERROR, tts_tag(), "[Player] Fail to play audio data. player(%p), uid(%u)", player, player->uid);
563 g_playing_info = NULL;
564 g_audio_stream->unprepareAudioOut();
565 __unset_policy_for_playing();
569 ttse_result_event_e event = sound_data->event;
570 int utt_id = sound_data->utt_id;
572 if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(player->uid)) {
573 ttsd_data_destroy_sound_data(sound_data);
575 sound_data = nullptr;
577 if (TTSE_RESULT_EVENT_FINISH == event) {
578 ret = __notify_utterance_completed_event(player->uid, utt_id);
579 if (TTSD_ERROR_NONE != ret) {
580 g_audio_stream->unprepareAudioOut();
581 __unset_policy_for_playing();
584 } // (TTSE_RESULT_EVENT_FINISH == event)
586 app_tts_state_e state = ttsd_data_get_client_state(player->uid);
587 if (APP_STATE_READY == state) {
589 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread");
591 /* Request prepare */
592 g_audio_stream->unprepareAudioOut();
593 /* unset volume policy, volume will be 100% */
594 __unset_policy_for_playing();
596 } // (APP_STATE_READY == state)
598 if (NULL == g_playing_info) {
599 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
600 g_audio_stream->unprepareAudioOut();
601 /* unset volume policy, volume will be 100% */
602 __unset_policy_for_playing();
605 } // end of 1st while(1)
608 static void __play_thread(void *data, Ecore_Thread *thread)
610 SLOG(LOG_INFO, tts_tag(), "[Player] play thread is on");
612 while (g_player_init) {
613 SLOG(LOG_INFO, tts_tag(), "[Player] Wait play request...");
614 pthread_mutex_lock(&g_play_thread_mutex);
615 pthread_cond_wait(&g_play_thread_cond, &g_play_thread_mutex);
616 if (false == g_player_init) {
617 SLOG(LOG_INFO, tts_tag(), "[Player] Player is released");
618 pthread_mutex_unlock(&g_play_thread_mutex);
622 __play_thread_old(data, thread);
623 pthread_mutex_unlock(&g_play_thread_mutex);
624 pthread_mutex_lock(&g_player_control_mutex);
625 g_playing_info = NULL;
626 pthread_mutex_unlock(&g_player_control_mutex);
633 int ttsd_player_init()
635 pthread_mutex_lock(&g_player_control_mutex);
636 g_playing_info = NULL;
638 ecore_thread_max_set(1);
640 g_background_volume = new BackgroundVolume(SND_MGR_DUCKING_DURATION);
641 g_audio_stream = new AudioStream(__focus_release_callback);
643 ecore_thread_max_set(1);
644 ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
646 g_is_set_policy = false;
647 g_player_init = true;
649 pthread_mutex_unlock(&g_player_control_mutex);
654 int ttsd_player_release(void)
657 __close_buffer_dump_file();
660 __set_playing_status(false);
661 pthread_mutex_lock(&g_player_control_mutex);
662 if (false == g_player_init) {
663 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
664 pthread_mutex_unlock(&g_player_control_mutex);
665 return TTSD_ERROR_OPERATION_FAILED;
668 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@");
669 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
670 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@");
672 /* The thread should be released */
673 int thread_count = ecore_thread_active_get();
675 while (0 < thread_count) {
680 SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
684 thread_count = ecore_thread_active_get();
687 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Thread is released");
689 /* clear g_player_list */
690 g_playing_info = NULL;
691 g_player_init = false;
692 pthread_cond_broadcast(&g_play_thread_cond);
694 delete g_audio_stream;
695 g_audio_stream = nullptr;
697 delete g_background_volume;
698 g_background_volume = nullptr;
700 pthread_mutex_unlock(&g_player_control_mutex);
705 int ttsd_player_create_instance(unsigned int uid)
707 if (false == g_player_init) {
708 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
709 return TTSD_ERROR_OPERATION_FAILED;
712 /* Check uid is duplicated */
713 if (NULL != __player_get_item(uid)) {
714 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is already registered", uid);
718 player_s* new_client = (player_s*)calloc(1, sizeof(player_s));
719 if (NULL == new_client) {
720 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to allocate memory");
721 return TTSE_ERROR_OUT_OF_MEMORY;
724 new_client->uid = uid;
725 new_client->event = TTSE_RESULT_EVENT_FINISH;
726 ttsd_data_set_paused_data_existing(uid, false);
728 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Player] Create player : uid(%u)", uid);
730 g_player_list = g_list_append(g_player_list, new_client);
735 int ttsd_player_destroy_instance(unsigned int uid)
737 pthread_mutex_lock(&g_player_control_mutex);
738 if (false == g_player_init) {
739 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
740 pthread_mutex_unlock(&g_player_control_mutex);
741 return TTSD_ERROR_OPERATION_FAILED;
745 current = __player_get_item(uid);
746 if (NULL == current) {
747 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
748 pthread_mutex_unlock(&g_player_control_mutex);
752 if (NULL != g_playing_info) {
753 if (uid == g_playing_info->uid) {
754 g_playing_info = NULL;
759 player_s *data = NULL;
761 if (0 < g_list_length(g_player_list)) {
762 /* Get a first item */
763 iter = g_list_first(g_player_list);
765 while (NULL != iter) {
766 /* Get handle data from list */
767 data = (player_s*)iter->data;
771 if (uid == data->uid) {
772 g_player_list = g_list_remove_link(g_player_list, iter);
781 iter = g_list_next(iter);
784 pthread_mutex_unlock(&g_player_control_mutex);
786 SLOG(LOG_DEBUG, tts_tag(), "[PLAYER Success] Destroy instance");
791 int ttsd_player_play(unsigned int uid)
793 pthread_mutex_lock(&g_player_control_mutex);
794 if (false == g_player_init) {
795 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
796 pthread_mutex_unlock(&g_player_control_mutex);
797 return TTSD_ERROR_OPERATION_FAILED;
800 if (NULL != g_playing_info) {
801 if (uid == g_playing_info->uid) {
802 SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%u) has already played", g_playing_info->uid);
803 pthread_mutex_unlock(&g_player_control_mutex);
806 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%u)", g_playing_info->uid);
807 pthread_mutex_unlock(&g_player_control_mutex);
808 ttsd_player_stop(g_playing_info->uid);
809 pthread_mutex_lock(&g_player_control_mutex);
813 SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%u)", uid);
817 current = __player_get_item(uid);
818 if (NULL == current) {
819 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
820 pthread_mutex_unlock(&g_player_control_mutex);
824 g_playing_info = current;
826 SLOG(LOG_INFO, tts_tag(), "[Player] Run thread");
827 pthread_cond_broadcast(&g_play_thread_cond);
829 pthread_mutex_unlock(&g_player_control_mutex);
833 int ttsd_player_stop(unsigned int uid)
835 pthread_mutex_lock(&g_player_control_mutex);
836 if (false == g_player_init) {
837 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
838 pthread_mutex_unlock(&g_player_control_mutex);
839 return TTSD_ERROR_OPERATION_FAILED;
842 /* check whether uid is current playing or not */
843 if (NULL != g_playing_info) {
844 if (uid == g_playing_info->uid) {
845 /* release current playing info */
846 g_playing_info = NULL;
849 SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
852 if (NULL == g_playing_info) {
853 pthread_mutex_lock(&g_play_thread_mutex);
854 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
855 pthread_mutex_unlock(&g_play_thread_mutex);
859 __close_buffer_dump_file();
862 __set_playing_status(false);
863 int ret = ttsd_player_clear(uid);
865 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to stop player, ret(%d)", ret);
866 pthread_mutex_unlock(&g_player_control_mutex);
870 SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Stop player : uid(%u)", uid);
872 pthread_mutex_unlock(&g_player_control_mutex);
876 int ttsd_player_clear(unsigned int uid)
878 if (false == g_player_init) {
879 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
880 return TTSD_ERROR_OPERATION_FAILED;
885 current = __player_get_item(uid);
886 if (NULL == current) {
887 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
891 current->event = TTSE_RESULT_EVENT_FINISH;
892 ttsd_data_set_paused_data_existing(uid, false);
894 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Clear player : uid(%u)", uid);
899 int ttsd_player_pause(unsigned int uid)
901 pthread_mutex_lock(&g_player_control_mutex);
902 SLOG(LOG_DEBUG, tts_tag(), "[Player] pause player : uid(%u)", uid);
904 if (false == g_player_init) {
905 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
906 pthread_mutex_unlock(&g_player_control_mutex);
907 return TTSD_ERROR_OPERATION_FAILED;
912 current = __player_get_item(uid);
913 if (NULL == current) {
914 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%u) is not valid", uid);
915 pthread_mutex_unlock(&g_player_control_mutex);
919 /* check whether uid is current playing or not */
920 if (NULL != g_playing_info) {
921 if (uid == g_playing_info->uid) {
922 /* release current playing info */
923 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release current playing info (%u)", uid);
924 g_playing_info = NULL;
930 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] current player (%p), g_playing_info(%p)", current, g_playing_info);
932 if (NULL == g_playing_info) {
933 pthread_mutex_lock(&g_play_thread_mutex);
934 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
935 pthread_mutex_unlock(&g_play_thread_mutex);
939 __close_buffer_dump_file();
942 __set_playing_status(false);
943 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Pause player : uid(%u)", uid);
945 pthread_mutex_unlock(&g_player_control_mutex);
949 int ttsd_player_resume(unsigned int uid)
951 pthread_mutex_lock(&g_player_control_mutex);
952 SLOG(LOG_DEBUG, tts_tag(), "[Player] Resume player : uid(%u)", uid);
954 if (false == g_player_init) {
955 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
956 pthread_mutex_unlock(&g_player_control_mutex);
957 return TTSD_ERROR_OPERATION_FAILED;
962 current = __player_get_item(uid);
963 if (NULL == current) {
964 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
965 pthread_mutex_unlock(&g_player_control_mutex);
969 /* check current player */
970 if (NULL != g_playing_info)
971 g_playing_info = NULL;
973 g_playing_info = current;
975 SLOG(LOG_INFO, tts_tag(), "[Player] Resume to run thread");
976 pthread_cond_broadcast(&g_play_thread_cond);
978 pthread_mutex_unlock(&g_player_control_mutex);
982 int ttsd_player_all_stop()
984 pthread_mutex_lock(&g_player_control_mutex);
985 if (false == g_player_init) {
986 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
987 pthread_mutex_unlock(&g_player_control_mutex);
988 return TTSD_ERROR_OPERATION_FAILED;
991 g_playing_info = NULL;
994 player_s *data = NULL;
996 if (0 < g_list_length(g_player_list)) {
997 /* Get a first item */
998 iter = g_list_first(g_player_list);
1000 while (NULL != iter) {
1001 /* Get handle data from list */
1002 data = (player_s*)iter->data;
1004 app_tts_state_e state = ttsd_data_get_client_state(data->uid);
1005 if (APP_STATE_NONE == state) {
1006 SLOG(LOG_ERROR, tts_tag(), "[player ERROR] uid(%u) is not valid", data->uid);
1007 iter = g_list_next(iter);
1009 pthread_mutex_unlock(&g_player_control_mutex);
1010 ttsd_player_destroy_instance(data->uid);
1011 pthread_mutex_lock(&g_player_control_mutex);
1015 if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
1016 data->event = TTSE_RESULT_EVENT_FINISH;
1017 ttsd_data_set_paused_data_existing(data->uid, false);
1021 iter = g_list_next(iter);
1025 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!");
1027 pthread_mutex_unlock(&g_player_control_mutex);
1031 int ttsd_player_get_background_volume_ratio(double* ratio)
1033 if (false == g_player_init) {
1034 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1035 return TTSD_ERROR_OPERATION_FAILED;
1038 if (NULL == ratio) {
1039 return TTSD_ERROR_INVALID_PARAMETER;
1042 *ratio = g_background_volume->getVolumeRatio();
1043 return TTSD_ERROR_NONE;
1046 int ttsd_player_set_background_volume_ratio(double ratio)
1048 if (false == g_player_init) {
1049 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1050 return TTSD_ERROR_OPERATION_FAILED;
1053 SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] ttsd_player_set_background_volume_ratio : %lf", ratio);
1054 g_background_volume->setVolumeRatio(ratio);
1056 return TTSD_ERROR_NONE;
1059 int ttsd_player_wait_to_play(unsigned int uid)
1061 if (false == g_player_init) {
1062 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1063 return TTSD_ERROR_OPERATION_FAILED;
1066 SLOG(LOG_INFO, tts_tag(), "[Player INFO] wait to play (%u)", uid);
1068 g_audio_stream->waitForPlay();
1069 return TTSD_ERROR_NONE;