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.
14 #include "ttsd_main.h"
15 #include "ttsd_data.h"
17 #include "ttsd_player.h"
18 #include "ttsd_state.h"
20 #include "BackgroundVolume.h"
21 #include "AudioStream.h"
22 #include "PlayerThread.h"
25 #define SOUND_BUFFER_LENGTH 2048
28 If you change this constant value. Please check the function 'set_timer_for_delay_recover()'.
29 If you choose too big value, it may cause integer overflow issue.
31 static const int SND_MGR_DUCKING_DURATION = 500;
32 static const intptr_t CHECK_TIMER_DELETE = 1;
33 static const int EXTRA_INFO_LENGTH = 20;
35 /* Sound buf save for test */
36 #define TTS_BUF_SAVE_FILE "/usr/share/tts_pcm_save"
37 static bool g_is_buf_save = false;
38 static char g_temp_file_name[128] = {'\0',};
40 static int g_count = 0;
41 static pthread_mutex_t g_buf_save_mutex = PTHREAD_MUTEX_INITIALIZER;
43 /** player init info */
44 static bool g_player_init = false;
46 static std::atomic<bool> g_is_set_policy(false);
48 static BackgroundVolume* g_background_volume = nullptr;
49 static AudioStream* g_audio_stream = nullptr;
50 static PlayerThread* g_player_thread = nullptr;
55 static void set_playing_status(bool is_playing)
57 int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, is_playing ? 1 : 0);
58 SLOG(LOG_INFO, tts_tag(), "[Player] Set playing status (%s). ret(%d)", is_playing ? "True" : "False", ret);
61 ttsd_state_set_state(TTSD_STATE_PLAYING);
63 if (ttsd_data_get_synth_control() == TTSD_SYNTHESIS_CONTROL_DOING) {
64 ttsd_state_set_state(TTSD_STATE_SYNTHESIZING);
66 ttsd_state_set_state(TTSD_STATE_READY);
71 static void open_buffer_dump_file()
73 pthread_mutex_lock(&g_buf_save_mutex);
75 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is already opened(%s)", g_temp_file_name);
76 pthread_mutex_unlock(&g_buf_save_mutex);
82 snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/tts_temp_%d_%d", getpid(), g_count);
83 int ret = access(g_temp_file_name, 0);
86 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File is already exist");
87 if (0 == remove(g_temp_file_name)) {
88 SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Remove file");
98 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Recorder] Temp file name=[%s]", g_temp_file_name);
101 g_pFile = fopen(g_temp_file_name, "wb+x");
102 if (NULL == g_pFile) {
103 SLOG(LOG_ERROR, tts_tag(), "[Recorder ERROR] File not found!");
106 pthread_mutex_unlock(&g_buf_save_mutex);
109 static void close_buffer_dump_file()
111 pthread_mutex_lock(&g_buf_save_mutex);
118 pthread_mutex_unlock(&g_buf_save_mutex);
121 static void write_buffer_dump_file(const void* buffer, size_t length)
123 pthread_mutex_lock(&g_buf_save_mutex);
126 size_t ret = fwrite(buffer, 1, length, g_pFile);
127 SLOG(LOG_DEBUG, tts_tag(), "[Buffer Dump] Stored size(%zu / %zu)", ret, length);
129 SLOG(LOG_ERROR, tts_tag(), "[Buffer Dump] File is not opened. Please check the file open");
132 pthread_mutex_unlock(&g_buf_save_mutex);
135 static int check_and_create_audio_stream(void)
137 if (nullptr != g_audio_stream)
140 SLOG(LOG_ERROR, tts_tag(), "[BG] g_audio_stream is null. Create a new instance");
141 g_audio_stream = new AudioStream();
142 if (nullptr == g_audio_stream) {
143 SLOG(LOG_ERROR, tts_tag(), "[BG] Fail to allocate memory.");
150 static void set_policy_for_playing(unsigned int uid)
152 /* In case of DEFAULT and INTERRUPT mode, acquire sound focus */
153 ttsd_mode_e mode = ttsd_data_get_mode(uid);
154 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Current uid(%d)'s mode(%d)", uid, (int)mode);
156 if (-1 == check_and_create_audio_stream())
159 if (TTSD_MODE_DEFAULT == mode || TTSD_MODE_INTERRUPT == mode)
160 g_audio_stream->acquireSoundFocus();
162 g_audio_stream->setSoundStreamInfo();
163 g_background_volume->applyVolumeRatio();
164 g_is_set_policy = true;
165 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", static_cast<int>(g_is_set_policy.load()));
166 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] set policy for playing");
169 static void unset_policy_for_playing(unsigned int uid)
171 /* In case of DEFAULT and INTERRUPT mode, release sound focus */
172 ttsd_mode_e mode = ttsd_data_get_mode(uid);
173 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Current uid(%d)'s mode(%d)", uid, (int)mode);
175 if ((TTSD_MODE_DEFAULT == mode || TTSD_MODE_INTERRUPT == mode) && nullptr != g_audio_stream)
176 g_audio_stream->releaseSoundFocus();
178 g_background_volume->recoverVolumeRatio();
179 g_is_set_policy = false;
180 SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", static_cast<int>(g_is_set_policy.load()));
181 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] unset policy for playing");
184 static int notify_utterance_started_event(unsigned int uid, int utt_id)
186 int pid = ttsd_data_get_pid(uid);
188 SLOG(LOG_ERROR, tts_tag(), "[Player] Current player is not valid. uid(%u)", uid);
189 return TTSD_ERROR_INVALID_PARAMETER;
192 if (true == g_is_buf_save) {
193 open_buffer_dump_file();
195 set_playing_status(true);
197 if (0 != ttsdc_ipc_send_utt_start_message(pid, uid, utt_id)) {
198 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to send Utterance Started Signal : pid(%d), uid(%u), utt_id(%d)",
200 return TTSD_ERROR_OPERATION_FAILED;
203 SLOG(LOG_INFO, tts_tag(), "[Player] Start utterance : uid(%u), utt_id(%d)", uid, utt_id);
204 return TTSD_ERROR_NONE;
207 static int notify_utterance_completed_event(unsigned int uid, int utt_id)
209 int pid = ttsd_data_get_pid(uid);
211 SLOG(LOG_ERROR, tts_tag(), "[Player] Current player is not valid. uid(%u)", uid);
212 return TTSD_ERROR_INVALID_PARAMETER;
215 if (true == g_is_buf_save) {
216 close_buffer_dump_file();
218 set_playing_status(false);
220 if (0 != ttsdc_ipc_send_utt_finish_message(pid, uid, utt_id)) {
221 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%u), utt_id(%d)",
223 return TTSD_ERROR_OPERATION_FAILED;
226 SLOG(LOG_INFO, tts_tag(), "[Player] Complete utterance : uid(%u), utt_id(%d)", uid, utt_id);
227 return TTSD_ERROR_NONE;
230 static int play_sound_data(PlayerThread* player, unsigned int uid, sound_data_s* sound_data)
232 if (-1 == check_and_create_audio_stream())
233 return TTSD_ERROR_OUT_OF_MEMORY;
235 if (TTSD_ERROR_NONE != g_audio_stream->setAudioFormat(sound_data->audio_type, sound_data->rate)) {
236 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out");
237 return TTSD_ERROR_OPERATION_FAILED;
240 // Check whether set_policy is done or not
241 if (false == g_is_set_policy.load()) {
242 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Set policy. uid(%d)", uid);
243 set_policy_for_playing(uid);
246 if (TTSD_ERROR_NONE != g_audio_stream->prepareAudioOut()) {
247 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to prepare audio");
248 return TTSD_ERROR_OPERATION_FAILED;
251 unsigned int idx = sound_data->played_data_size;
252 while (idx < sound_data->data_size) {
253 app_tts_state_e state = ttsd_data_get_client_state(uid);
254 if (APP_STATE_PLAYING != state && APP_STATE_PAUSED != state) {
258 unsigned int len = 0;
259 if (idx + SOUND_BUFFER_LENGTH > sound_data->data_size) {
260 len = sound_data->data_size - idx;
262 len = SOUND_BUFFER_LENGTH;
265 char* temp_data = sound_data->data;
266 SLOG(LOG_INFO, tts_tag(), "[Player INFO] Before audio_out_write. data(%p), data[%d](%p), uid(%u), utt_id(%d), len(%u)",
267 temp_data, idx, &temp_data[idx], uid, sound_data->utt_id, len);
269 if (true == g_is_buf_save) {
270 write_buffer_dump_file(&temp_data[idx], len);
273 if (TTSD_ERROR_NONE != g_audio_stream->playAudioData(&temp_data[idx], len)) {
274 SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to write audio");
277 sound_data->played_data_size = idx;
278 SLOG(LOG_INFO, tts_tag(), "[Player INFO] After audio_out_write");
281 if (APP_STATE_PAUSED == state) {
282 return TTSD_ERROR_INVALID_STATE;
285 if (false == player->isCurrentUid(uid)) {
286 return TTSD_ERROR_OPERATION_FAILED;
290 return TTSD_ERROR_NONE;
293 static void wait_sound_data(PlayerThread* player, unsigned int uid)
295 ttsd_synthesis_control_e prev_synth_control = TTSD_SYNTHESIS_CONTROL_EXPIRED;
296 while (0 >= ttsd_data_get_sound_data_size(uid)) {
298 if (false == player->isCurrentUid(uid)) {
302 /* If engine is not on processing */
303 ttsd_synthesis_control_e synth_control = ttsd_data_get_synth_control();
304 if (prev_synth_control != synth_control)
305 SLOG(LOG_INFO, tts_tag(), "[Server INFO] prev_synth_control(%d), synth_control(%d)", prev_synth_control, synth_control);
306 if (TTSD_SYNTHESIS_CONTROL_DOING != synth_control) {
307 if (AudioStream::AUDIO_STATE_PLAY == g_audio_stream->getState()) {
308 g_audio_stream->unprepareAudioOut();
309 unset_policy_for_playing(uid); // uid == current uid
312 prev_synth_control = synth_control;
316 static void set_paused_data(unsigned int uid, sound_data_s* sound_data) {
317 int ret = ttsd_data_set_paused_data(uid, sound_data);
318 if (TTSD_ERROR_NONE != ret) {
319 ttsd_data_destroy_sound_data(sound_data);
323 static void play_utterance_cb(PlayerThread* player, unsigned int uid)
325 SLOG(LOG_DEBUG, tts_tag(), "[PLAYER] Start play utterance. uid(%u)", uid);
327 while (player->isCurrentUid(uid)) {
328 sound_data_s* sound_data = ttsd_data_get_first_sound_data(uid);
329 if (ttsd_data_is_paused_data_existing(uid)) {
330 ttsd_data_set_paused_data(uid, nullptr);
332 if (nullptr == sound_data) {
335 set_playing_status(true);
337 SLOG(LOG_INFO, tts_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)",
338 sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event);
340 if (nullptr == sound_data) {
341 SLOG(LOG_ERROR, tts_tag(), "[Player] No sound data. Waiting mode");
343 wait_sound_data(player, uid);
344 if (false == player->isCurrentUid(uid)) {
345 SLOG(LOG_INFO, tts_tag(), "[Player] Finish thread");
349 SLOG(LOG_INFO, tts_tag(), "[Player] Finish to wait for new audio data come");
353 /* If wdata's event is 'start', current wdata is first data of engine for synthesis.
354 * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
355 * When previous wdata's event is 'finish' and current wdata's event is 'finish',
356 * the player should send utt started event.
358 ttse_result_event_e last_event = ttsd_data_get_last_sound_result_event(uid);
359 if (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == last_event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
360 int ret = notify_utterance_started_event(uid, sound_data->utt_id);
361 if (TTSD_ERROR_INVALID_PARAMETER == ret) {
366 /* Save last event to check utterance start */
367 ttsd_data_set_last_sound_result_event(uid, sound_data->event);
369 if (nullptr == sound_data->data || 0 >= sound_data->data_size) {
370 ttse_result_event_e event = sound_data->event;
371 int utt_id = sound_data->utt_id;
373 ttsd_data_destroy_sound_data(sound_data);
374 sound_data = nullptr;
376 SLOG(LOG_INFO, tts_tag(), "[Player] No Sound data. Event(%d), uid(%u), uttid(%d)", event, uid, utt_id);
377 if (TTSE_RESULT_EVENT_FINISH == event) {
378 unset_policy_for_playing(uid);
379 if (TTSD_ERROR_INVALID_PARAMETER == notify_utterance_completed_event(uid, utt_id)) {
388 int ret = play_sound_data(player, uid, sound_data);
389 if (TTSD_ERROR_INVALID_STATE == ret) {
390 SLOG(LOG_DEBUG, tts_tag(), "[Player] Uid(%u) is paused", uid);
391 set_paused_data(uid, sound_data);
393 } else if (TTSD_ERROR_NONE != ret) {
394 SLOG(LOG_ERROR, tts_tag(), "[Player] Fail to play audio data. uid(%u)", uid);
395 ttsd_data_destroy_sound_data(sound_data);
396 sound_data = nullptr;
400 ttse_result_event_e event = sound_data->event;
401 int utt_id = sound_data->utt_id;
403 ttsd_data_destroy_sound_data(sound_data);
404 sound_data = nullptr;
406 if (TTSE_RESULT_EVENT_FINISH == event) {
407 unset_policy_for_playing(uid);
408 if (TTSD_ERROR_NONE != notify_utterance_completed_event(uid, utt_id)) {
413 app_tts_state_e state = ttsd_data_get_client_state(uid);
414 if (APP_STATE_READY == state) {
416 SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread");
421 g_audio_stream->unprepareAudioOut();
422 unset_policy_for_playing(uid);
424 if (true == g_is_buf_save) {
425 close_buffer_dump_file();
428 SLOG(LOG_DEBUG, tts_tag(), "[PLAYER] Finish play utterance. uid(%u)", uid);
434 int ttsd_player_init()
436 g_background_volume = new BackgroundVolume(SND_MGR_DUCKING_DURATION);
437 g_player_thread = new PlayerThread(play_utterance_cb);
439 g_is_set_policy = false;
440 g_player_init = true;
445 int ttsd_player_release(void)
447 if (true == g_is_buf_save) {
448 close_buffer_dump_file();
451 set_playing_status(false);
452 if (false == g_player_init) {
453 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
454 return TTSD_ERROR_OPERATION_FAILED;
457 g_player_init = false;
458 g_player_thread->requestStop();
459 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Thread is released");
461 delete g_player_thread;
462 g_player_thread = nullptr;
464 delete g_audio_stream;
465 g_audio_stream = nullptr;
467 delete g_background_volume;
468 g_background_volume = nullptr;
470 SLOG(LOG_INFO, tts_tag(), "[Player] ttsd_player_release succeed");
474 int ttsd_player_play(unsigned int uid)
476 if (false == g_player_init) {
477 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
478 return TTSD_ERROR_OPERATION_FAILED;
481 if (0 > ttsd_data_is_client(uid)) {
482 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
486 unsigned int currentUid = g_player_thread->getCurrentUid();
487 if (0 < ttsd_data_is_client(currentUid) && uid == currentUid) {
488 SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%u) has already played", uid);
489 return TTSD_ERROR_NONE;
492 /* check whether saving PCM buffer or not */
493 if (0 == access(TTS_BUF_SAVE_FILE, 0)) {
494 SLOG(LOG_DEBUG, tts_tag(), "[Player] Save PCM buffers");
495 g_is_buf_save = true;
497 SLOG(LOG_DEBUG, tts_tag(), "[Player] Do not save PCM buffers");
498 g_is_buf_save = false;
501 SLOG(LOG_INFO, tts_tag(), "[Player] start play : uid(%u)", uid);
502 g_player_thread->requestPlay(uid);
507 int ttsd_player_stop(unsigned int uid)
509 if (false == g_player_init) {
510 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
511 return TTSD_ERROR_OPERATION_FAILED;
514 if (uid == g_player_thread->getCurrentUid()) {
515 g_player_thread->requestStop();
517 SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
520 if (true == g_is_buf_save) {
521 close_buffer_dump_file();
524 set_playing_status(false);
525 ttsd_data_set_last_sound_result_event(uid, TTSE_RESULT_EVENT_FINISH);
526 ttsd_data_set_paused_data(uid, nullptr);
528 SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Stop player : uid(%u)", uid);
533 int ttsd_player_pause(unsigned int uid)
535 SLOG(LOG_DEBUG, tts_tag(), "[Player] pause player : uid(%u)", uid);
537 if (false == g_player_init) {
538 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
539 return TTSD_ERROR_OPERATION_FAILED;
542 if (0 > ttsd_data_is_client(uid)) {
543 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%u) is not valid", uid);
547 if (uid == g_player_thread->getCurrentUid()) {
548 SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release current playing info (%u)", uid);
549 g_player_thread->requestStop();
552 if (true == g_is_buf_save) {
553 close_buffer_dump_file();
556 set_playing_status(false);
557 SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Pause player : uid(%u)", uid);
561 static bool stop_all_client_callback(int pid, unsigned int uid, app_tts_state_e state, void* user_data)
563 if (0 > ttsd_data_is_client(uid)) {
564 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
568 if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
569 ttsd_data_set_last_sound_result_event(uid, TTSE_RESULT_EVENT_FINISH);
570 ttsd_data_set_paused_data(uid, nullptr);
576 int ttsd_player_all_stop()
578 if (false == g_player_init) {
579 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
580 return TTSD_ERROR_OPERATION_FAILED;
583 g_player_thread->requestStop();
584 ttsd_data_foreach_clients(stop_all_client_callback, nullptr);
586 SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!");
587 return TTSD_ERROR_NONE;
590 int ttsd_player_get_background_volume_ratio(double* ratio)
592 if (false == g_player_init) {
593 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
594 return TTSD_ERROR_OPERATION_FAILED;
597 if (nullptr == ratio) {
598 return TTSD_ERROR_INVALID_PARAMETER;
601 *ratio = g_background_volume->getVolumeRatio();
602 return TTSD_ERROR_NONE;
605 int ttsd_player_set_background_volume_ratio(double ratio)
607 if (false == g_player_init) {
608 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
609 return TTSD_ERROR_OPERATION_FAILED;
612 SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] ttsd_player_set_background_volume_ratio : %lf", ratio);
613 g_background_volume->setVolumeRatio(ratio);
615 return TTSD_ERROR_NONE;
618 int ttsd_player_wait_to_play(unsigned int uid)
620 if (false == g_player_init) {
621 SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized");
622 return TTSD_ERROR_OPERATION_FAILED;
625 if (-1 == check_and_create_audio_stream())
626 return TTSD_ERROR_OUT_OF_MEMORY;
628 SLOG(LOG_INFO, tts_tag(), "[Player INFO] wait to play (%u)", uid);
630 g_audio_stream->waitForPlay();
631 return TTSD_ERROR_NONE;