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 */
35 app_tts_state_e state; /** client state */
37 /* Current utterance information */
38 ttse_result_event_e event; /** event of last utterance */
42 sound_data_s* paused_data;
45 #define SOUND_BUFFER_LENGTH 2048
47 static const intptr_t CHECK_TIMER_DELETE = 1;
48 static const int EXTRA_INFO_LENGTH = 20;
50 /* Sound buf save for test */
56 static char g_temp_file_name[128] = {'\0',};
58 static int g_count = 0;
59 static pthread_mutex_t g_buf_save_mutex = PTHREAD_MUTEX_INITIALIZER;
62 /** player init info */
63 static bool g_player_init = false;
66 static GList *g_player_list;
68 /** current player information */
69 static player_s* g_playing_info;
71 static bool g_is_set_policy;
74 If you change this constant value. Please check the function '__set_timer_for_delay_recover()'.
75 If you choose too big value, it may cause integer overflow issue.
77 #define SND_MGR_DUCKING_DURATION 500
79 static pthread_mutex_t g_play_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
80 static pthread_mutex_t g_player_control_mutex = PTHREAD_MUTEX_INITIALIZER;
82 static pthread_cond_t g_play_thread_cond = PTHREAD_COND_INITIALIZER;
84 static BackgroundVolume* g_background_volume = nullptr;
85 static AudioStream* g_audio_stream = nullptr;
90 static void __set_playing_status(bool is_playing)
92 int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, is_playing ? 1 : 0);
93 SLOG(LOG_INFO, tts_tag(), "[Player] Set playing status (%s). ret(%d)", is_playing ? "True" : "False", ret);
97 static void __open_buffer_dump_file()
99 pthread_mutex_lock(&g_buf_save_mutex);
101 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is already opened(%s)", g_temp_file_name);
102 pthread_mutex_unlock(&g_buf_save_mutex);
108 snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/tts_temp_%d_%d", getpid(), g_count);
109 int ret = access(g_temp_file_name, 0);
112 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File is already exist");
113 if (0 == remove(g_temp_file_name)) {
114 SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Remove file");
124 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Temp file name=[%s]", g_temp_file_name);
127 g_pFile = fopen(g_temp_file_name, "wb+x");
128 if (NULL == g_pFile) {
129 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File not found!");
132 pthread_mutex_unlock(&g_buf_save_mutex);
135 static void __close_buffer_dump_file()
137 pthread_mutex_lock(&g_buf_save_mutex);
144 pthread_mutex_unlock(&g_buf_save_mutex);
147 static void __write_buffer_dump_file(const void* buffer, size_t length)
149 pthread_mutex_lock(&g_buf_save_mutex);
152 size_t ret = fwrite(buffer, 1, length, g_pFile);
153 SLOG(LOG_DEBUG, tts_tag(), "[Buffer Dump] Stored size(%zu / %zu)", ret, length);
155 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is not opened. Please check the file open");
158 pthread_mutex_unlock(&g_buf_save_mutex);
162 static bool __is_player_valid(player_s* player)
164 if (NULL == player || NULL == g_playing_info) {
165 SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is NULL");
169 if (g_playing_info != player || g_playing_info->uid != player->uid) {
170 SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is not current player");
177 player_s* __player_get_item(unsigned int uid)
180 player_s *data = NULL;
182 if (0 < g_list_length(g_player_list)) {
183 /* Get a first item */
184 iter = g_list_first(g_player_list);
186 while (NULL != iter) {
187 /* Get handle data from list */
188 data = (player_s*)iter->data;
191 if (uid == data->uid)
195 iter = g_list_next(iter);
202 static void __focus_release_callback()
204 if (NULL == g_playing_info) {
205 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player");
209 if (APP_STATE_PLAYING != g_playing_info->state) {
213 unsigned int uid = g_playing_info->uid;
214 ttsd_mode_e mode = ttsd_data_get_mode(uid);
217 case TTSD_MODE_DEFAULT:
219 SLOG(LOG_DEBUG, tts_tag(), "[Player] Pause current player - mode(%d)", mode);
220 if (0 != ttsd_player_pause(uid)) {
221 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to pause the player");
225 ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
226 int pid = ttsd_data_get_pid(uid);
228 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to get pid. uid(%u)", uid);
230 /* send message to client about changing state */
231 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Player paused. pid(%d), uid(%u)", pid, uid);
232 ttsdc_ipc_send_set_state_message(pid, uid, APP_STATE_PAUSED);
237 case TTSD_MODE_NOTIFICATION:
238 case TTSD_MODE_SCREEN_READER:
240 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop current player - mode(%d)", mode);
241 ttsd_send_all_stop();
245 case TTSD_MODE_INTERRUPT:
246 SLOG(LOG_DEBUG, tts_tag(), "[Player] Ignore focus release - mode(%d)", mode);
250 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Invalid mode - mode(%d)", mode);
254 SLOG(LOG_DEBUG, tts_tag(), "@@@");
259 static void __end_play_thread(void *data, Ecore_Thread *thread)
261 SLOG(LOG_ERROR, tts_tag(), "@@@ End thread");
264 static void __set_policy_for_playing(void)
266 const char* extra_info = NULL;
267 if (TTSD_MODE_INTERRUPT == ttsd_get_mode()) {
268 extra_info = "TTSD_MODE_INTERRUPT";
271 g_audio_stream->acquireSoundFocus(extra_info);
272 g_background_volume->applyVolumeRatio();
273 g_is_set_policy = true;
274 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
275 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] set policy for playing");
280 static void __unset_policy_for_playing()
282 g_audio_stream->releaseSoundFocus();
283 g_background_volume->recoverVolumeRatio();
284 g_is_set_policy = false;
285 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
286 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] unset policy for playing");
291 static bool __does_interrupt_have_focus(sound_stream_focus_change_reason_e reason, int sound_behavior, char *extra_info)
293 SLOG(LOG_DEBUG, tts_tag(), "[Player] current Playback focus: extra_info(%s), reason(%d), sound_behavior(%d)", extra_info, reason, sound_behavior);
294 if (SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION != reason) {
298 if (NULL == extra_info || 0 >= strlen(extra_info) || 0 != strncmp(extra_info, "TTSD_MODE_INTERRUPT", EXTRA_INFO_LENGTH)) {
305 bool ttsd_player_does_interrupt_have_playback_focus()
307 sound_stream_focus_change_reason_e reason;
308 int sound_behavior = 0;
309 char *extra_info = NULL;
310 if (SOUND_MANAGER_ERROR_NONE != sound_manager_get_current_playback_focus(&reason, &sound_behavior, &extra_info)) {
311 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to get focus information");
315 bool result = __does_interrupt_have_focus(reason, sound_behavior, extra_info);
320 static void __play_thread_old(void *data, Ecore_Thread *thread)
322 SLOG(LOG_DEBUG, tts_tag(), "@@@ Start thread");
324 if (NULL == g_playing_info) {
325 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] No current player");
329 player_s* player = g_playing_info;
330 sound_data_s* sound_data = NULL;
333 int len = SOUND_BUFFER_LENGTH;
336 /* set volume policy as 40% */
337 __set_policy_for_playing();
338 while (1) { // 1st while(1)
339 /* check g_playing_info one more time */
340 if (false == __is_player_valid(player)) {
341 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Player is not valid");
342 g_audio_stream->unprepareAudioOut();
343 __unset_policy_for_playing();
347 if (true == player->is_paused_data && NULL != player->paused_data) {
349 sound_data_s* paused_data = player->paused_data;
350 player->paused_data = NULL;
352 ttsd_data_destroy_sound_data(sound_data);
353 sound_data = ttsd_data_create_sound_data(paused_data->utt_id, paused_data->data, paused_data->data_size,
354 paused_data->event, paused_data->audio_type, paused_data->rate, paused_data->channels);
355 if (NULL == sound_data || paused_data->data_size <= 0) {
356 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Out of memory OR paused_data is empty");
357 ttsd_data_destroy_sound_data(sound_data);
358 sound_data = paused_data;
359 } else { // NULL != sound_data && NULL != temp && player->paused_data->data_size > 0
360 ttsd_data_destroy_sound_data(paused_data);
365 player->is_paused_data = false;
368 if (NULL == sound_data) {
369 /* Request unprepare */
370 g_audio_stream->unprepareAudioOut();
372 /* unset volume policy, volume will be 100% */
373 __unset_policy_for_playing();
376 __set_playing_status(true);
378 SLOG(LOG_INFO, tts_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)",
379 sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event);
380 } else { // NO player->is_paused_data
382 ret = ttsd_data_get_sound_data(player->uid, &sound_data);
383 if (0 != ret || NULL == sound_data) {
385 SLOG(LOG_ERROR, tts_tag(), "[Player] No sound data. Waiting mode");
387 /* wait for new audio data come */
388 while (1) { // 2nd while(1)
390 if (false == __is_player_valid(player)) {
391 /* current playing uid is replaced */
392 SLOG(LOG_INFO, tts_tag(), "[Player] Finish thread");
393 if (AudioStream::AUDIO_STATE_PLAY == g_audio_stream->getState()) {
394 /* release audio & recover session */
395 g_audio_stream->unprepareAudioOut();
397 /* unset volume policy, volume will be 100% */
398 __unset_policy_for_playing();
400 } else if (0 < ttsd_data_get_sound_data_size(player->uid)) {
401 /* new audio data come */
402 SLOG(LOG_INFO, tts_tag(), "[Player] Resume thread");
403 break; // exit from 2nd while(1)
406 /* If engine is not on processing */
407 ttsd_synthesis_control_e synth_control = ttsd_get_synth_control();
408 if (TTSD_SYNTHESIS_CONTROL_DOING != synth_control) {
409 SLOG(LOG_INFO, tts_tag(), "[Server INFO] synth_control(%d)", synth_control);
410 if (AudioStream::AUDIO_STATE_PLAY == g_audio_stream->getState()) {
411 /* release audio & recover session */
412 g_audio_stream->unprepareAudioOut();
414 /* unset volume policy, volume will be 100% */
415 __unset_policy_for_playing();
418 } // end of 2nd while(1). waiting for new audio data come
420 SLOG(LOG_INFO, tts_tag(), "[Player] Finish to wait for new audio data come");
422 if (AudioStream::AUDIO_STATE_READY == g_audio_stream->getState() || AudioStream::AUDIO_STATE_WAIT_FOR_PLAYING == g_audio_stream->getState()) {
423 /* set volume policy as 40%, when resume play thread*/
424 __set_policy_for_playing();
427 /* resume play thread */
428 player->state = APP_STATE_PLAYING;
430 } // NULL == sound_data
432 /* If wdata's event is 'start', current wdata is first data of engine for synthesis.
433 * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
434 * When previous wdata's event is 'finish' and current wdata's event is 'finish',
435 * the player should send utt started event.
437 if (TTSE_RESULT_EVENT_START == sound_data->event ||
438 (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
439 int pid = ttsd_data_get_pid(player->uid);
441 SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid. uid(%u)", player->uid);
442 /* unset volume policy, volume will be 100% */
443 __unset_policy_for_playing();
444 ttsd_data_destroy_sound_data(sound_data);
450 __open_buffer_dump_file();
453 __set_playing_status(true);
454 if (0 != ttsdc_ipc_send_utt_start_message(pid, player->uid, sound_data->utt_id)) {
455 SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%u), uttid(%d)",
456 pid, player->uid, sound_data->utt_id);
458 SLOG(LOG_INFO, tts_tag(), "[Player] Start utterance : uid(%u), uttid(%d)", player->uid, sound_data->utt_id);
459 } // (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event))
461 /* Save last event to check utterance start */
462 player->event = sound_data->event;
465 if (NULL == sound_data->data || 0 >= sound_data->data_size) {
466 if (TTSE_RESULT_EVENT_FINISH == sound_data->event) {
467 SLOG(LOG_DEBUG, tts_tag(), "No sound data");
468 /* send utterence finish signal */
469 int pid = ttsd_data_get_pid(player->uid);
472 SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid. uid(%u)", player->uid);
473 /* unset volume policy, volume will be 100% */
474 __unset_policy_for_playing();
475 ttsd_data_destroy_sound_data(sound_data);
480 __unset_policy_for_playing();
483 __close_buffer_dump_file();
486 __set_playing_status(false);
487 if (0 != ttsdc_ipc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) {
488 SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%u), uttid(%d)",
489 pid, player->uid, sound_data->utt_id);
491 SLOG(LOG_INFO, tts_tag(), "[Player] Finish utterance : uid(%u), uttid(%d)", player->uid, sound_data->utt_id);
493 } // TTSE_RESULT_EVENT_FINISH == sound_data->event
494 SLOG(LOG_INFO, tts_tag(), "[Player] Event(%d) utterance : uid(%u), uttid(%d)", sound_data->event, player->uid, sound_data->utt_id);
495 ttsd_data_destroy_sound_data(sound_data);
498 } // (NULL == sound_data->data || 0 >= sound_data->data_size)
499 } // NO player->is_paused_data
501 // If there is any change in audio format, recreate audio handle
502 if (TTSD_ERROR_NONE != g_audio_stream->setAudioFormat(sound_data->audio_type, sound_data->rate)) {
503 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out");
504 /* unset volume policy, volume will be 100% */
505 __unset_policy_for_playing();
507 ttsd_data_destroy_sound_data(sound_data);
512 while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) {
513 if ((unsigned int)idx >= sound_data->data_size)
516 if ((unsigned int)idx + SOUND_BUFFER_LENGTH > sound_data->data_size) {
517 len = sound_data->data_size - idx;
519 len = SOUND_BUFFER_LENGTH;
522 // Check whether set_policy is done or not
523 if (false == g_is_set_policy) {
524 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Set policy");
525 __set_policy_for_playing();
528 if (AudioStream::AUDIO_STATE_READY == g_audio_stream->getState() || AudioStream::AUDIO_STATE_WAIT_FOR_PLAYING == g_audio_stream->getState()) {
529 /* Request prepare */
530 ret = g_audio_stream->prepareAudioOut();
531 if (TTSD_ERROR_NONE != ret) {
532 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to prepare audio : %d", ret);
534 /* unset volume policy, volume will be 100% */
535 __unset_policy_for_playing();
536 ttsd_data_destroy_sound_data(sound_data);
541 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Prepare audio");
544 char* temp_data = sound_data->data;
545 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Before audio_out_write. data(%p), data[%d](%p), uid(%u), utt_id(%d), len(%d)",
546 temp_data, idx, &temp_data[idx], player->uid, sound_data->utt_id, len);
548 __write_buffer_dump_file(&temp_data[idx], len);
550 ret = g_audio_stream->playAudioData(&temp_data[idx], len);
551 if (TTSD_ERROR_NONE != ret) {
552 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to audio write - %d", ret);
555 SLOG(LOG_INFO, tts_tag(), "[Player INFO] After audio_out_write");
558 if (NULL == g_playing_info && APP_STATE_PAUSED != player->state) {
559 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
560 g_audio_stream->unprepareAudioOut();
561 /* unset volume policy, volume will be 100% */
562 __unset_policy_for_playing();
564 ttsd_data_destroy_sound_data(sound_data);
567 } // (NULL == g_playing_info && APP_STATE_PAUSED != player->state)
569 if (APP_STATE_PAUSED == player->state) {
571 SLOG(LOG_DEBUG, tts_tag(), "[Player] player(%p)", player);
572 ttsd_data_destroy_sound_data(player->paused_data);
573 player->paused_data = sound_data;
575 player->is_paused_data = true;
579 SLOG(LOG_INFO, tts_tag(), "[Player] Stop player thread by pause");
581 /* Request prepare */
582 g_audio_stream->unprepareAudioOut();
583 /* unset volume policy, volume will be 100% */
584 __unset_policy_for_playing();
586 } // (APP_STATE_PAUSED == player->state)
587 } // while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state)
589 if (NULL == g_playing_info && APP_STATE_READY == player->state) {
591 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread");
593 /* Request prepare */
594 g_audio_stream->unprepareAudioOut();
595 /* unset volume policy, volume will be 100% */
596 __unset_policy_for_playing();
597 ttsd_data_destroy_sound_data(sound_data);
600 } // (NULL == g_playing_info && APP_STATE_READY == player->state)
602 if ((APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) &&
603 (TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
604 /* send utterence finish signal */
605 int pid = ttsd_data_get_pid(player->uid);
608 SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid. uid(%u)", player->uid);
609 /* unset volume policy, volume will be 100% */
610 __unset_policy_for_playing();
611 ttsd_data_destroy_sound_data(sound_data);
617 __close_buffer_dump_file();
619 __set_playing_status(false);
620 if (0 != ttsdc_ipc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) {
621 SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%u), uttid(%d)",
622 pid, player->uid, sound_data->utt_id);
623 /* unset volume policy, volume will be 100% */
624 __unset_policy_for_playing();
625 ttsd_data_destroy_sound_data(sound_data);
630 SLOG(LOG_INFO, tts_tag(), "[Player] Finish utterance : uid(%u), uttid(%d)", player->uid, sound_data->utt_id);
631 } // ((APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) && (TTSE_RESULT_EVENT_FINISH == sound_data->event))
633 ttsd_data_destroy_sound_data(sound_data);
636 if (NULL == g_playing_info) {
637 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
638 g_audio_stream->unprepareAudioOut();
639 /* unset volume policy, volume will be 100% */
640 __unset_policy_for_playing();
641 ttsd_data_destroy_sound_data(sound_data);
645 } // end of 1st while(1)
648 static void __play_thread(void *data, Ecore_Thread *thread)
650 SLOG(LOG_INFO, tts_tag(), "[Player] play thread is on");
652 while (g_player_init) {
653 SLOG(LOG_INFO, tts_tag(), "[Player] Wait play request...");
654 pthread_mutex_lock(&g_play_thread_mutex);
655 pthread_cond_wait(&g_play_thread_cond, &g_play_thread_mutex);
656 if (false == g_player_init) {
657 SLOG(LOG_INFO, tts_tag(), "[Player] Player is released");
658 pthread_mutex_unlock(&g_play_thread_mutex);
662 __play_thread_old(data, thread);
663 pthread_mutex_unlock(&g_play_thread_mutex);
664 pthread_mutex_lock(&g_player_control_mutex);
665 g_playing_info = NULL;
666 pthread_mutex_unlock(&g_player_control_mutex);
673 int ttsd_player_init()
675 pthread_mutex_lock(&g_player_control_mutex);
676 g_playing_info = NULL;
678 ecore_thread_max_set(1);
680 g_background_volume = new BackgroundVolume(SND_MGR_DUCKING_DURATION);
681 g_audio_stream = new AudioStream(__focus_release_callback);
683 ecore_thread_max_set(1);
684 ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
686 g_is_set_policy = false;
687 g_player_init = true;
689 pthread_mutex_unlock(&g_player_control_mutex);
694 int ttsd_player_release(void)
697 __close_buffer_dump_file();
700 __set_playing_status(false);
701 pthread_mutex_lock(&g_player_control_mutex);
702 if (false == g_player_init) {
703 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
704 pthread_mutex_unlock(&g_player_control_mutex);
705 return TTSD_ERROR_OPERATION_FAILED;
708 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@");
709 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get());
710 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@");
712 /* The thread should be released */
713 int thread_count = ecore_thread_active_get();
715 while (0 < thread_count) {
720 SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue.");
724 thread_count = ecore_thread_active_get();
727 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Thread is released");
729 /* clear g_player_list */
730 g_playing_info = NULL;
731 g_player_init = false;
732 pthread_cond_broadcast(&g_play_thread_cond);
734 delete g_audio_stream;
735 g_audio_stream = nullptr;
737 delete g_background_volume;
738 g_background_volume = nullptr;
740 pthread_mutex_unlock(&g_player_control_mutex);
745 int ttsd_player_create_instance(unsigned int uid)
747 if (false == g_player_init) {
748 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
749 return TTSD_ERROR_OPERATION_FAILED;
752 /* Check uid is duplicated */
753 if (NULL != __player_get_item(uid)) {
754 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is already registered", uid);
758 player_s* new_client = (player_s*)calloc(1, sizeof(player_s));
759 if (NULL == new_client) {
760 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to allocate memory");
761 return TTSE_ERROR_OUT_OF_MEMORY;
764 new_client->uid = uid;
765 new_client->event = TTSE_RESULT_EVENT_FINISH;
766 new_client->state = APP_STATE_READY;
767 new_client->is_paused_data = false;
769 new_client->paused_data = NULL;
771 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Player] Create player : uid(%u)", uid);
773 g_player_list = g_list_append(g_player_list, new_client);
778 int ttsd_player_destroy_instance(unsigned int uid)
780 pthread_mutex_lock(&g_player_control_mutex);
781 if (false == g_player_init) {
782 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
783 pthread_mutex_unlock(&g_player_control_mutex);
784 return TTSD_ERROR_OPERATION_FAILED;
788 current = __player_get_item(uid);
789 if (NULL == current) {
790 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
791 pthread_mutex_unlock(&g_player_control_mutex);
795 if (NULL != g_playing_info) {
796 if (uid == g_playing_info->uid) {
797 g_playing_info = NULL;
802 player_s *data = NULL;
804 if (0 < g_list_length(g_player_list)) {
805 /* Get a first item */
806 iter = g_list_first(g_player_list);
808 while (NULL != iter) {
809 /* Get handle data from list */
810 data = (player_s*)iter->data;
814 if (uid == data->uid) {
815 g_player_list = g_list_remove_link(g_player_list, iter);
824 iter = g_list_next(iter);
827 pthread_mutex_unlock(&g_player_control_mutex);
829 SLOG(LOG_DEBUG, tts_tag(), "[PLAYER Success] Destroy instance");
834 int ttsd_player_play(unsigned int uid)
836 pthread_mutex_lock(&g_player_control_mutex);
837 if (false == g_player_init) {
838 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
839 pthread_mutex_unlock(&g_player_control_mutex);
840 return TTSD_ERROR_OPERATION_FAILED;
843 if (NULL != g_playing_info) {
844 if (uid == g_playing_info->uid) {
845 SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%u) has already played", g_playing_info->uid);
846 pthread_mutex_unlock(&g_player_control_mutex);
849 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%u)", g_playing_info->uid);
850 pthread_mutex_unlock(&g_player_control_mutex);
851 ttsd_player_stop(g_playing_info->uid);
852 pthread_mutex_lock(&g_player_control_mutex);
856 SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%u)", uid);
860 current = __player_get_item(uid);
861 if (NULL == current) {
862 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
863 pthread_mutex_unlock(&g_player_control_mutex);
867 current->state = APP_STATE_PLAYING;
868 g_playing_info = current;
870 SLOG(LOG_INFO, tts_tag(), "[Player] Run thread");
871 pthread_cond_broadcast(&g_play_thread_cond);
873 pthread_mutex_unlock(&g_player_control_mutex);
877 int ttsd_player_stop(unsigned int uid)
879 pthread_mutex_lock(&g_player_control_mutex);
880 if (false == g_player_init) {
881 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
882 pthread_mutex_unlock(&g_player_control_mutex);
883 return TTSD_ERROR_OPERATION_FAILED;
886 /* check whether uid is current playing or not */
887 if (NULL != g_playing_info) {
888 if (uid == g_playing_info->uid) {
889 /* release current playing info */
890 g_playing_info = NULL;
893 SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
896 if (NULL == g_playing_info) {
897 pthread_mutex_lock(&g_play_thread_mutex);
898 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
899 pthread_mutex_unlock(&g_play_thread_mutex);
903 __close_buffer_dump_file();
906 __set_playing_status(false);
907 int ret = ttsd_player_clear(uid);
909 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to stop player, ret(%d)", ret);
910 pthread_mutex_unlock(&g_player_control_mutex);
914 SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Stop player : uid(%u)", uid);
916 pthread_mutex_unlock(&g_player_control_mutex);
920 int ttsd_player_clear(unsigned int uid)
922 if (false == g_player_init) {
923 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
924 return TTSD_ERROR_OPERATION_FAILED;
929 current = __player_get_item(uid);
930 if (NULL == current) {
931 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
935 if (true == current->is_paused_data) {
936 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Clear paused data");
937 ttsd_data_destroy_sound_data(current->paused_data);
938 current->paused_data = NULL;
941 current->event = TTSE_RESULT_EVENT_FINISH;
942 current->state = APP_STATE_READY;
943 current->is_paused_data = false;
946 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Clear player : uid(%u)", uid);
951 int ttsd_player_pause(unsigned int uid)
953 pthread_mutex_lock(&g_player_control_mutex);
954 SLOG(LOG_DEBUG, tts_tag(), "[Player] pause player : uid(%u)", uid);
956 if (false == g_player_init) {
957 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
958 pthread_mutex_unlock(&g_player_control_mutex);
959 return TTSD_ERROR_OPERATION_FAILED;
964 current = __player_get_item(uid);
965 if (NULL == current) {
966 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%u) is not valid", uid);
967 pthread_mutex_unlock(&g_player_control_mutex);
971 /* check whether uid is current playing or not */
972 if (NULL != g_playing_info) {
973 if (uid == g_playing_info->uid) {
974 /* release current playing info */
975 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release current playing info (%u)", uid);
976 g_playing_info = NULL;
982 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] current player (%p), g_playing_info(%p)", current, g_playing_info);
984 current->state = APP_STATE_PAUSED;
986 if (NULL == g_playing_info) {
987 pthread_mutex_lock(&g_play_thread_mutex);
988 SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
989 pthread_mutex_unlock(&g_play_thread_mutex);
993 __close_buffer_dump_file();
996 __set_playing_status(false);
997 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Pause player : uid(%u)", uid);
999 pthread_mutex_unlock(&g_player_control_mutex);
1003 int ttsd_player_resume(unsigned int uid)
1005 pthread_mutex_lock(&g_player_control_mutex);
1006 SLOG(LOG_DEBUG, tts_tag(), "[Player] Resume player : uid(%u)", uid);
1008 if (false == g_player_init) {
1009 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1010 pthread_mutex_unlock(&g_player_control_mutex);
1011 return TTSD_ERROR_OPERATION_FAILED;
1016 current = __player_get_item(uid);
1017 if (NULL == current) {
1018 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
1019 pthread_mutex_unlock(&g_player_control_mutex);
1023 /* check current player */
1024 if (NULL != g_playing_info)
1025 g_playing_info = NULL;
1027 current->state = APP_STATE_PLAYING;
1028 g_playing_info = current;
1030 SLOG(LOG_INFO, tts_tag(), "[Player] Resume to run thread");
1031 pthread_cond_broadcast(&g_play_thread_cond);
1033 pthread_mutex_unlock(&g_player_control_mutex);
1037 int ttsd_player_all_stop()
1039 pthread_mutex_lock(&g_player_control_mutex);
1040 if (false == g_player_init) {
1041 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1042 pthread_mutex_unlock(&g_player_control_mutex);
1043 return TTSD_ERROR_OPERATION_FAILED;
1046 g_playing_info = NULL;
1049 player_s *data = NULL;
1051 if (0 < g_list_length(g_player_list)) {
1052 /* Get a first item */
1053 iter = g_list_first(g_player_list);
1055 while (NULL != iter) {
1056 /* Get handle data from list */
1057 data = (player_s*)iter->data;
1059 app_tts_state_e state;
1060 if (0 > ttsd_data_get_client_state(data->uid, &state)) {
1061 SLOG(LOG_ERROR, tts_tag(), "[player ERROR] uid(%u) is not valid", data->uid);
1062 iter = g_list_next(iter);
1064 pthread_mutex_unlock(&g_player_control_mutex);
1065 ttsd_player_destroy_instance(data->uid);
1066 pthread_mutex_lock(&g_player_control_mutex);
1070 if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
1071 data->event = TTSE_RESULT_EVENT_FINISH;
1072 data->state = APP_STATE_READY;
1074 if (true == data->is_paused_data) {
1075 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Clear paused data");
1076 ttsd_data_destroy_sound_data(data->paused_data);
1077 data->paused_data = NULL;
1080 data->is_paused_data = false;
1085 iter = g_list_next(iter);
1089 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!");
1091 pthread_mutex_unlock(&g_player_control_mutex);
1095 int ttsd_player_get_background_volume_ratio(double* ratio)
1097 if (false == g_player_init) {
1098 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1099 return TTSD_ERROR_OPERATION_FAILED;
1102 if (NULL == ratio) {
1103 return TTSD_ERROR_INVALID_PARAMETER;
1106 *ratio = g_background_volume->getVolumeRatio();
1107 return TTSD_ERROR_NONE;
1110 int ttsd_player_set_background_volume_ratio(double ratio)
1112 if (false == g_player_init) {
1113 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1114 return TTSD_ERROR_OPERATION_FAILED;
1117 SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] ttsd_player_set_background_volume_ratio : %lf", ratio);
1118 g_background_volume->setVolumeRatio(ratio);
1120 return TTSD_ERROR_NONE;
1123 int ttsd_player_wait_to_play(unsigned int uid)
1125 if (false == g_player_init) {
1126 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
1127 return TTSD_ERROR_OPERATION_FAILED;
1130 SLOG(LOG_INFO, tts_tag(), "[Player INFO] wait to play (%u)", uid);
1132 g_audio_stream->waitForPlay();
1133 return TTSD_ERROR_NONE;