2 * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #include "vc_mgr_player.h"
26 #include "vc_mgr_data.h"
35 vc_feedback_state_e state;
37 vc_feedback_event_e event;
41 #define SOUND_BUFFER_LENGTH 2048
43 static bool g_player_init = false;
45 static player_s* g_playing_info;
47 static audio_state_e g_audio_state;
49 static vc_audio_type_e g_audio_type;
51 static vc_audio_channel_e g_audio_channel;
53 static int g_sampling_rate;
55 static audio_out_h g_audio_h;
58 static int __create_audio_out(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type)
61 audio_channel_e sample_channel = 0;
62 audio_sample_type_e sample_type = 0;
64 if (VC_AUDIO_CHANNEL_MONO == channel) {
65 sample_channel = AUDIO_CHANNEL_MONO;
66 } else if (VC_AUDIO_CHANNEL_STEREO == channel) {
67 sample_channel = AUDIO_CHANNEL_STEREO;
70 if (VC_AUDIO_TYPE_PCM_S16_LE == audio_type) {
71 sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
73 sample_type = AUDIO_SAMPLE_TYPE_U8;
76 /* create audio_out new */
77 ret = audio_out_create_new(rate, sample_channel, sample_type, &g_audio_h);
78 if (AUDIO_IO_ERROR_NONE != ret) {
79 g_audio_state = AUDIO_STATE_NONE;
81 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to create audio. ret(%d)", ret);
84 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Create audio");
87 g_audio_channel = channel;
88 g_audio_type = audio_type;
89 g_sampling_rate = rate;
91 g_audio_state = AUDIO_STATE_READY;
96 static int __destroy_audio_out()
98 if (NULL == g_audio_h) {
99 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current handle is not valid");
104 ret = audio_out_destroy(g_audio_h);
105 if (AUDIO_IO_ERROR_NONE != ret) {
106 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to destroy audio. ret(%d)", ret);
109 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Destroy audio");
116 g_audio_state = AUDIO_STATE_NONE;
122 int vc_mgr_player_init(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type)
124 g_audio_state = AUDIO_STATE_NONE;
127 ecore_thread_max_set(1);
132 ret = __create_audio_out(rate, channel, audio_type);
134 return VC_ERROR_OPERATION_FAILED;
137 g_player_init = true;
139 return VC_ERROR_NONE;
142 int vc_mgr_player_release()
144 if (false == g_player_init) {
145 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized");
146 return VC_ERROR_OPERATION_FAILED;
151 int thread_count = ecore_thread_active_get();
152 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Active thread count : %d", thread_count);
154 while (0 < thread_count) {
159 SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Thread is blocked. Player release continue");
163 thread_count = ecore_thread_active_get();
166 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Thread is release");
168 ret = __destroy_audio_out();
170 return VC_ERROR_OPERATION_FAILED;
173 g_player_init = false;
175 return VC_ERROR_NONE;
178 static void __play_feedback_thread(void* data, Ecore_Thread* thread)
180 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Start thread");
182 if (NULL == g_playing_info) {
183 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] No current player");
187 player_s* player = g_playing_info;
188 vc_feedback_data_s* feedback_data = NULL;
191 int len = SOUND_BUFFER_LENGTH;
195 /* get feedback data */
196 ret = vc_mgr_data_get_feedback_data(&feedback_data);
197 if (0 != ret || NULL == feedback_data) {
199 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No feedback data. Waiting mode");
204 if (0 < vc_mgr_data_get_feedback_data_size()) {
205 SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Resume thread");
209 if (AUDIO_STATE_PLAY == g_audio_state) {
210 /* release audio & recover session */
211 ret = audio_out_unprepare(g_audio_h);
212 if (AUDIO_IO_ERROR_NONE != ret) {
213 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio");
215 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Unprepare audio");
217 g_audio_state = AUDIO_STATE_READY;
221 SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Finish to wait for new feedback data come");
223 /* resume play thread */
224 player->state = VC_FEEDBACK_STATE_PLAYING;
228 if (VC_FEEDBACK_EVENT_START == feedback_data->event ||
229 (VC_FEEDBACK_EVENT_FINISH == player->event && VC_FEEDBACK_EVENT_FINISH == feedback_data->event)) {
230 int pid = vc_mgr_data_get_pid();
231 SLOG(LOG_INFO, TAG_VCM, "[Player DEBUG] Start utterance (%d)", pid);
234 player->event = feedback_data->event;
236 /* If no feedback data and EVENT_FINISH */
237 if (NULL == feedback_data->data || 0 >= feedback_data->data_size) {
238 if (VC_FEEDBACK_EVENT_FINISH == feedback_data->event) {
239 int pid = vc_mgr_data_get_pid();
243 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No sound data");
245 SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Finish utterance");
246 vc_mgr_data_clear_feedback_data(&feedback_data);
250 if (g_sampling_rate != feedback_data->rate || g_audio_type != feedback_data->audio_type || g_audio_channel != feedback_data->channel) {
251 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] change audio handle");
252 if (NULL != g_audio_h) {
253 __destroy_audio_out();
256 if (0 > __create_audio_out(feedback_data->rate, feedback_data->channel, feedback_data->audio_type)) {
257 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to create audio out");
258 vc_mgr_data_clear_feedback_data(&feedback_data);
264 while (VC_FEEDBACK_STATE_PLAYING == player->state) {
265 if ((unsigned int)idx >= feedback_data->data_size)
268 if ((unsigned int)idx + SOUND_BUFFER_LENGTH > feedback_data->data_size) {
269 len = feedback_data->data_size - idx;
271 len = SOUND_BUFFER_LENGTH;
274 if (AUDIO_STATE_READY == g_audio_state) {
275 /* request prepare */
276 ret = audio_out_prepare(g_audio_h);
277 if (AUDIO_IO_ERROR_NONE != ret) {
278 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to prepare audio");
279 vc_mgr_data_clear_feedback_data(&feedback_data);
282 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Prepare audio");
283 g_audio_state = AUDIO_STATE_PLAY;
286 char* temp_data = feedback_data->data;
287 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] data(%p), idx(%d), len(%d)", temp_data, idx, len);
289 ret = audio_out_write(g_audio_h, &temp_data[idx], len);
291 SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Fail to audio write - %d", ret);
296 if (NULL == g_playing_info) {
297 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current player is NULL");
298 g_audio_state = AUDIO_STATE_READY;
299 ret = audio_out_unprepare(g_audio_h);
300 if (AUDIO_IO_ERROR_NONE != ret) {
301 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio");
304 vc_mgr_data_clear_feedback_data(&feedback_data);
310 if (NULL == g_playing_info && VC_FEEDBACK_STATE_READY == player->state) {
312 g_audio_state = AUDIO_STATE_READY;
313 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Stop play thread");
315 /* request to unprepare audio */
316 ret = audio_out_unprepare(g_audio_h);
317 if (AUDIO_IO_ERROR_NONE != ret) {
318 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio");
320 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Unprepare audio");
323 vc_mgr_data_clear_feedback_data(&feedback_data);
327 if ((VC_FEEDBACK_STATE_PLAYING == player->state) && (VC_FEEDBACK_EVENT_FINISH == feedback_data->event)) {
328 int pid = vc_mgr_data_get_pid();
332 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Finish utterance");
335 vc_mgr_data_clear_feedback_data(&feedback_data);
337 if (NULL == g_playing_info) {
338 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current player is NULL");
339 g_audio_state = AUDIO_STATE_READY;
340 ret = audio_out_unprepare(g_audio_h);
341 if (AUDIO_IO_ERROR_NONE != ret) {
342 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio");
352 static void __end_play_feedback_thread(void* data, Ecore_Thread* thread)
354 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] End thread");
357 int vc_mgr_player_play()
359 if (false == g_player_init) {
360 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized");
361 return VC_ERROR_OPERATION_FAILED;
364 if (NULL != g_playing_info) {
365 SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Stop old player");
366 vc_mgr_player_stop();
369 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] start play");
371 /* check sound queue size */
372 int data_size = vc_mgr_data_get_feedback_data_size();
373 if (0 == data_size) {
374 SLOG(LOG_WARN, TAG_VCM, "[Player WARN] A sound queue of current player is empty");
375 } else if (0 < data_size) {
376 SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Run thread");
377 ecore_thread_run(__play_feedback_thread, __end_play_feedback_thread, NULL, NULL);
380 return VC_ERROR_NONE;
383 int vc_mgr_player_stop()
385 if (false == g_player_init) {
386 SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized");
387 return VC_ERROR_OPERATION_FAILED;
390 if (NULL != g_playing_info) {
391 g_playing_info = NULL;
392 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No more current playing");
395 SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] stop play");
397 int thread_count = ecore_thread_active_get();
400 while (0 < thread_count) {
405 SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Thread is blocked. Player release continue");
409 thread_count = ecore_thread_active_get();
412 return VC_ERROR_NONE;