4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jeongmo Yang <jm80.yang@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*=======================================================================================
24 =======================================================================================*/
26 #include <mm_sound_private.h>
28 #include <audio-session-manager.h>
29 #include "mm_camcorder_internal.h"
30 #include "mm_camcorder_sound.h"
32 /*---------------------------------------------------------------------------------------
33 | GLOBAL VARIABLE DEFINITIONS for internal |
34 ---------------------------------------------------------------------------------------*/
36 /*---------------------------------------------------------------------------------------
37 | LOCAL VARIABLE DEFINITIONS for internal |
38 ---------------------------------------------------------------------------------------*/
39 #define SAMPLE_SOUND_NAME "camera-shutter"
40 #define SAMPLE_SOUND_RATE 44100
41 #define DEFAULT_ACTIVE_DEVICE -1
44 SOUND_DEVICE_TYPE_SPEAKER, /* AVSYS_AUDIO_LVOL_DEV_TYPE_SPK */
45 SOUND_DEVICE_TYPE_HEADSET, /* AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET */
46 SOUND_DEVICE_TYPE_BTHEADSET, /* AVSYS_AUDIO_LVOL_DEV_TYPE_BTHEADSET */
47 SOUND_DEVICE_TYPE_NUM /* AVSYS_AUDIO_LVOL_DEV_TYPE_MAX */
50 /*---------------------------------------------------------------------------------------
51 | LOCAL FUNCTION PROTOTYPES: |
52 ---------------------------------------------------------------------------------------*/
53 static void __solo_sound_callback(void *data);
56 static void __pulseaudio_context_state_cb(pa_context *pulse_context, void *user_data)
59 SOUND_INFO *info = NULL;
61 mmf_return_if_fail(user_data);
63 info = (SOUND_INFO *)user_data;
65 state = pa_context_get_state(pulse_context);
67 case PA_CONTEXT_READY:
68 _mmcam_dbg_log("pulseaudio context READY");
69 if (info->pulse_context == pulse_context) {
71 _mmcam_dbg_log("pulseaudio send signal");
72 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
75 case PA_CONTEXT_TERMINATED:
76 if (info->pulse_context == pulse_context) {
78 _mmcam_dbg_log("Context terminated : pulseaudio send signal");
79 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
82 case PA_CONTEXT_UNCONNECTED:
83 case PA_CONTEXT_CONNECTING:
84 case PA_CONTEXT_AUTHORIZING:
85 case PA_CONTEXT_SETTING_NAME:
86 case PA_CONTEXT_FAILED:
88 _mmcam_dbg_log("pulseaudio context %p, state %d",
89 pulse_context, state);
96 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
97 static void __pulseaudio_stream_write_cb(pa_stream *stream, size_t length, void *user_data)
99 sf_count_t read_length;
101 SOUND_INFO *info = NULL;
103 mmf_return_if_fail(user_data);
105 info = (SOUND_INFO *)user_data;
107 _mmcam_dbg_log("START");
109 data = pa_xmalloc(length);
111 read_length = (sf_count_t)(length/pa_frame_size(&(info->sample_spec)));
113 if ((sf_readf_short(info->infile, data, read_length)) != read_length) {
118 pa_stream_write(stream, data, length, pa_xfree, 0, PA_SEEK_RELATIVE);
120 info->sample_length -= length;
122 if (info->sample_length <= 0) {
123 pa_stream_set_write_callback(info->sample_stream, NULL, NULL);
124 pa_stream_finish_upload(info->sample_stream);
126 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
127 _mmcam_dbg_log("send signal DONE");
130 _mmcam_dbg_log("DONE read_length %d", read_length);
134 static void __pulseaudio_remove_sample_finish_cb(pa_context *pulse_context, int success, void *user_data)
136 SOUND_INFO *info = NULL;
138 mmf_return_if_fail(user_data);
140 info = (SOUND_INFO *)user_data;
142 _mmcam_dbg_log("START");
144 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
146 _mmcam_dbg_log("DONE");
148 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
150 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
151 gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename)
152 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
153 gboolean _mmcamcorder_sound_init(MMHandleType handle)
154 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
157 int sound_enable = TRUE;
158 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
159 SOUND_INFO *info = NULL;
160 mm_sound_device_in device_in;
161 mm_sound_device_out device_out;
162 pa_mainloop_api *api = NULL;
164 mmf_return_val_if_fail(hcamcorder, FALSE);
166 /* check sound play enable */
167 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
168 "capture-sound-enable", &sound_enable,
170 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
175 info = &(hcamcorder->snd_info);
177 pthread_mutex_lock(&(info->open_mutex));
179 if (info->state > _MMCAMCORDER_SOUND_STATE_NONE) {
180 _mmcam_dbg_warn("already initialized [%d]", info->state);
181 pthread_mutex_unlock(&(info->open_mutex));
185 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
186 if (info->filename) {
187 free(info->filename);
188 info->filename = NULL;
191 info->filename = strdup(filename);
192 if (info->filename == NULL) {
193 _mmcam_dbg_err("strdup failed");
196 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
198 pthread_mutex_init(&(info->play_mutex), NULL);
199 pthread_cond_init(&(info->play_cond), NULL);
201 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
203 memset (&(info->sfinfo), 0, sizeof(SF_INFO));
204 info->infile = sf_open(info->filename, SFM_READ, &(info->sfinfo));
205 if (!(info->infile)) {
206 _mmcam_dbg_err("Failed to open sound file");
207 goto SOUND_INIT_ERROR;
209 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
211 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON) {
213 ASM_resource_t mm_resource = mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_ENCODER;
215 /* set EXCLUSIVE session as PLAYING to pause other session */
216 if (!ASM_set_sound_state(hcamcorder->asm_handle_ex, ASM_EVENT_EXCLUSIVE_MMCAMCORDER,
217 ASM_STATE_PLAYING, mm_resource, &errorcode)) {
218 _mmcam_dbg_err("Set state to playing failed 0x%x", errorcode);
219 ret = MM_ERROR_POLICY_BLOCKED;
220 goto SOUND_INIT_ERROR;
223 _mmcam_dbg_log("EXCLUSIVE session PLAYING done.");
225 _mmcam_dbg_log("do not register session to pause another playing session");
229 * Init Pulseaudio thread
231 /* create pulseaudio mainloop */
232 info->pulse_mainloop = pa_threaded_mainloop_new();
233 ret = pa_threaded_mainloop_start(info->pulse_mainloop);
235 /* lock pulseaudio thread */
236 pa_threaded_mainloop_lock(info->pulse_mainloop);
237 /* get pulseaudio api */
238 api = pa_threaded_mainloop_get_api(info->pulse_mainloop);
239 /* create pulseaudio context */
240 info->pulse_context = pa_context_new(api, NULL);
241 /* set pulseaudio context callback */
242 pa_context_set_state_callback(info->pulse_context, __pulseaudio_context_state_cb, info);
244 if (pa_context_connect(info->pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
245 _mmcam_dbg_err("pa_context_connect error");
248 /* wait READY state of pulse context */
250 pa_context_state_t state = pa_context_get_state(info->pulse_context);
252 _mmcam_dbg_log("pa context state is now %d", state);
254 if (!PA_CONTEXT_IS_GOOD (state)) {
255 _mmcam_dbg_log("connection failed");
259 if (state == PA_CONTEXT_READY) {
260 _mmcam_dbg_log("pa context READY");
264 /* Wait until the context is ready */
265 _mmcam_dbg_log("waiting..................");
266 pa_threaded_mainloop_wait(info->pulse_mainloop);
267 _mmcam_dbg_log("waiting DONE. check again...");
270 /* unlock pulseaudio thread */
271 pa_threaded_mainloop_unlock(info->pulse_mainloop);
273 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
277 if (pa_sndfile_read_sample_spec(info->infile, &(info->sample_spec)) < 0) {
278 _mmcam_dbg_err("Failed to determine sample specification from file");
279 goto SOUND_INIT_ERROR;
282 info->sample_spec.format = PA_SAMPLE_S16LE;
284 if (pa_sndfile_read_channel_map(info->infile, &(info->channel_map)) < 0) {
285 pa_channel_map_init_extend(&(info->channel_map), info->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
287 if (info->sample_spec.channels > 2) {
288 _mmcam_dbg_warn("Failed to determine sample specification from file");
292 info->sample_length = (size_t)info->sfinfo.frames * pa_frame_size(&(info->sample_spec));
294 pa_threaded_mainloop_lock(info->pulse_mainloop);
296 /* prepare uploading */
297 info->sample_stream = pa_stream_new(info->pulse_context, SAMPLE_SOUND_NAME, &(info->sample_spec), NULL);
298 /* set stream write callback */
299 pa_stream_set_write_callback(info->sample_stream, __pulseaudio_stream_write_cb, info);
300 /* upload sample (ASYNC) */
301 pa_stream_connect_upload(info->sample_stream, info->sample_length);
302 /* wait for upload completion */
303 pa_threaded_mainloop_wait(info->pulse_mainloop);
305 pa_threaded_mainloop_unlock (info->pulse_mainloop);
308 sf_close(info->infile);
310 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
312 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON) {
313 /* backup current route */
314 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
316 __ta__(" mm_sound_get_active_device",
317 ret = mm_sound_get_active_device(&device_in, &device_out);
319 if (ret != MM_ERROR_NONE) {
320 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]. skip sound play.", ret);
321 goto SOUND_INIT_ERROR;
324 _mmcam_dbg_log("current out [%x]", device_out);
326 if (device_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
327 ret = mm_sound_set_active_route (MM_SOUND_ROUTE_OUT_SPEAKER);
328 if (ret != MM_ERROR_NONE) {
329 _mmcam_dbg_err("mm_sound_set_active_route failed [%x]. skip sound play.", ret);
330 goto SOUND_INIT_ERROR;
332 info->active_out_backup = device_out;
336 info->state = _MMCAMCORDER_SOUND_STATE_INIT;
338 _mmcam_dbg_log("init DONE");
340 pthread_mutex_unlock(&(info->open_mutex));
346 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
348 * Release allocated resources
350 if (info->filename) {
351 free(info->filename);
352 info->filename = NULL;
354 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
356 /* remove pulse mainloop */
357 if (info->pulse_mainloop) {
358 /* remove pulse context */
359 if (info->pulse_context) {
360 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
361 /* remove uploaded sample */
362 if (info->sample_stream) {
363 pa_threaded_mainloop_lock(info->pulse_mainloop);
365 /* Remove sample (ASYNC) */
366 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
368 /* Wait for async operation */
369 pa_threaded_mainloop_wait(info->pulse_mainloop);
371 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
373 /* Make sure we don't get any further callbacks */
374 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
376 pa_context_disconnect(info->pulse_context);
377 pa_context_unref(info->pulse_context);
378 info->pulse_context = NULL;
381 pa_threaded_mainloop_stop(info->pulse_mainloop);
382 pa_threaded_mainloop_free(info->pulse_mainloop);
383 info->pulse_mainloop = NULL;
386 /* remove mutex and cond */
387 pthread_mutex_destroy(&(info->play_mutex));
388 pthread_cond_destroy(&(info->play_cond));
390 pthread_mutex_unlock(&(info->open_mutex));
396 gboolean _mmcamcorder_sound_play(MMHandleType handle)
399 int sound_enable = TRUE;
400 int volume_type = AVSYS_AUDIO_VOLUME_TYPE_FIXED;
401 int device_type = SOUND_DEVICE_TYPE_SPEAKER;
402 int left_volume = 0, right_volume = 0;
403 float left_gain = 1.0f, right_gain = 1.0f;
406 unsigned int volume_level;
408 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
409 SOUND_INFO *info = NULL;
410 pa_operation *pulse_op = NULL;
412 mmf_return_val_if_fail(hcamcorder, FALSE);
414 /* check sound play enable */
415 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
416 "capture-sound-enable", &sound_enable,
418 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
423 info = &(hcamcorder->snd_info);
425 pthread_mutex_lock(&(info->open_mutex));
427 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
428 _mmcam_dbg_log("not initialized state:[%d]", info->state);
429 pthread_mutex_unlock(&(info->open_mutex));
433 /* get volume level and set volume */
434 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_OFF) {
435 gboolean sound_status = hcamcorder->sub_context->info_image->sound_status;
436 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
437 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
439 volume_type = AVSYS_AUDIO_VOLUME_TYPE_MEDIA;
440 avsys_audio_get_volume_max_ex(volume_type, &max_level);
443 __ta__(" mm_sound_get_active_device",
444 mm_sound_get_active_device(&device_in, &device_out);
447 _mmcam_dbg_log("sound status %d, device out %x", sound_status, device_out);
449 if (device_out == MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY) {
450 device_type = SOUND_DEVICE_TYPE_HEADSET;
451 } else if (device_out == MM_SOUND_DEVICE_OUT_BT_A2DP) {
452 device_type = SOUND_DEVICE_TYPE_BTHEADSET;
455 if (sound_status || device_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
456 volume_level = hcamcorder->sub_context->info_image->volume_level;
457 _mmcam_dbg_log("current volume level %d", volume_level);
460 _mmcam_dbg_log("current state is SILENT mode and SPEAKER output");
463 if (volume_level > (unsigned int)max_level) {
464 _mmcam_dbg_warn("invalid volume level. set max");
465 volume_level = (unsigned int)max_level;
468 avsys_audio_get_volume_max_ex(volume_type, &max_level);
469 volume_level = (unsigned int)max_level;
472 avsys_audio_get_volume_table(volume_type, device_type, (int)volume_level, &left_volume, &right_volume);
473 avsys_audio_get_volume_gain_table(
474 AVSYS_AUDIO_VOLUME_GAIN_IDX(AVSYS_AUDIO_VOLUME_GAIN_SHUTTER2),
475 device_type, &left_gain, &right_gain);
476 set_volume = left_volume * left_gain;
477 _mmcam_dbg_log("volume type %d, device type %d, volume level %d, left volume %d left gain %.2f set_volume %d",
478 volume_type, device_type, volume_level, left_volume, left_gain, set_volume);
480 _mmcam_dbg_log("shutter sound policy %d, volume %d",
481 hcamcorder->shutter_sound_policy, set_volume);
483 _mmcam_dbg_log("Play start");
485 __ta__(" pa_context_play_sample",
486 pulse_op = pa_context_play_sample(info->pulse_context,
494 pa_operation_unref(pulse_op);
498 pthread_mutex_unlock(&(info->open_mutex));
500 _mmcam_dbg_log("Done");
506 gboolean _mmcamcorder_sound_finalize(MMHandleType handle)
508 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
509 SOUND_INFO *info = NULL;
510 mm_sound_device_in device_in;
511 mm_sound_device_out device_out;
514 mmf_return_val_if_fail(hcamcorder, FALSE);
516 info = &(hcamcorder->snd_info);
518 _mmcam_dbg_err("START");
520 pthread_mutex_lock(&(info->open_mutex));
522 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
523 _mmcam_dbg_warn("not initialized");
524 pthread_mutex_unlock(&(info->open_mutex));
528 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON) {
532 _mmcam_dbg_log("restore route");
533 if (info->active_out_backup != DEFAULT_ACTIVE_DEVICE) {
534 ret = mm_sound_get_active_device(&device_in, &device_out);
535 if (ret != MM_ERROR_NONE) {
536 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]. skip sound play.", ret);
539 _mmcam_dbg_log("current out [%x]", device_out);
541 if (device_out != info->active_out_backup) {
542 ret = mm_sound_set_active_route (info->active_out_backup);
543 if (ret != MM_ERROR_NONE) {
544 _mmcam_dbg_err("mm_sound_set_active_route failed [%x]. skip sound play.", ret);
550 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
554 _mmcam_dbg_log("remove sample");
556 pa_threaded_mainloop_lock(info->pulse_mainloop);
558 /* Remove sample (ASYNC) */
559 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
561 /* Wait for async operation */
562 pa_threaded_mainloop_wait(info->pulse_mainloop);
564 pa_threaded_mainloop_unlock(info->pulse_mainloop);
565 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
568 * Release pulseaudio thread
570 _mmcam_dbg_log("release pulseaudio thread");
572 pa_threaded_mainloop_lock(info->pulse_mainloop);
574 pa_context_disconnect(info->pulse_context);
576 /* Make sure we don't get any further callbacks */
577 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
579 pa_context_unref(info->pulse_context);
580 info->pulse_context = NULL;
582 pa_threaded_mainloop_unlock(info->pulse_mainloop);
584 pa_threaded_mainloop_stop(info->pulse_mainloop);
585 pa_threaded_mainloop_free(info->pulse_mainloop);
586 info->pulse_mainloop = NULL;
588 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
589 if (info->filename) {
590 free(info->filename);
591 info->filename = NULL;
593 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
595 info->state = _MMCAMCORDER_SOUND_STATE_NONE;
596 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
598 /* release mutex and cond */
599 _mmcam_dbg_log("release play_mutex/cond");
600 pthread_mutex_destroy(&(info->play_mutex));
601 pthread_cond_destroy(&(info->play_cond));
603 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON) {
605 ASM_resource_t mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_ENCODER;
607 /* stop EXCLUSIVE session */
608 if (!ASM_set_sound_state(hcamcorder->asm_handle_ex, ASM_EVENT_EXCLUSIVE_MMCAMCORDER,
609 ASM_STATE_STOP, mm_resource, &errorcode)) {
610 _mmcam_dbg_err("EXCLUSIVE Set state to STOP failed 0x%x", errorcode);
612 _mmcam_dbg_log("EXCLUSIVE session STOP done.");
616 pthread_mutex_unlock(&(info->open_mutex));
618 _mmcam_dbg_err("DONE");
624 gboolean _mmcamcorder_sound_capture_play_cb(gpointer data)
626 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
628 mmf_return_val_if_fail(hcamcorder, FALSE);
630 _mmcam_dbg_log("Capture sound PLAY in idle callback");
632 _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE);
638 void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gboolean sync)
640 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
642 int sound_handle = 0;
643 int ret = MM_ERROR_NONE;
644 int sound_enable = TRUE;
645 int gain_type = VOLUME_GAIN_SHUTTER1;
647 mmf_return_if_fail(filepath && hcamcorder);
649 _mmcam_dbg_log("START : %s", filepath);
651 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
652 "capture-sound-enable", &sound_enable,
654 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
659 ret = pthread_mutex_trylock(&(hcamcorder->sound_lock));
661 _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret));
665 /* check filename to set gain_type */
666 if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE_SND)) {
667 gain_type = VOLUME_GAIN_SHUTTER1;
668 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE2_SND)) {
669 gain_type = VOLUME_GAIN_SHUTTER2;
670 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_START_SND) ||
671 !strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_STOP_SND)) {
672 gain_type = VOLUME_GAIN_CAMCORDING;
675 _mmcam_dbg_log("gain type 0x%x", gain_type);
677 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON) {
678 __ta__("CAPTURE SOUND:mm_sound_play_loud_solo_sound",
679 ret = mm_sound_play_loud_solo_sound(filepath, VOLUME_TYPE_FIXED | gain_type,
680 __solo_sound_callback, (void*)hcamcorder, &sound_handle);
683 gboolean sound_status = hcamcorder->sub_context->info_image->sound_status;
684 mm_sound_device_in device_in;
685 mm_sound_device_out device_out;
688 mm_sound_get_active_device(&device_in, &device_out);
690 _mmcam_dbg_log("sound status %d, device out %x", sound_status, device_out);
692 if (sound_status || device_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
693 __ta__("CAPTURE SOUND:mm_sound_play_sound",
694 ret = mm_sound_play_sound(filepath, VOLUME_TYPE_MEDIA | gain_type,
695 __solo_sound_callback, (void*)hcamcorder, &sound_handle);
699 if (ret != MM_ERROR_NONE) {
700 _mmcam_dbg_err( "Capture sound play FAILED.[%x]", ret );
703 struct timespec timeout;
706 gettimeofday( &tv, NULL );
707 timeout.tv_sec = tv.tv_sec + 2;
708 timeout.tv_nsec = tv.tv_usec * 1000;
710 _mmcam_dbg_log("Wait for signal");
712 MMTA_ACUM_ITEM_BEGIN("CAPTURE SOUND:wait sound play finish", FALSE);
714 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
715 _mmcam_dbg_log("signal received.");
717 _mmcam_dbg_warn("capture sound play timeout.");
718 if (sound_handle > 0) {
719 mm_sound_stop_sound(sound_handle);
723 MMTA_ACUM_ITEM_END("CAPTURE SOUND:wait sound play finish", FALSE);
727 pthread_mutex_unlock(&(hcamcorder->sound_lock));
729 _mmcam_dbg_log("DONE");
734 static void __solo_sound_callback(void *data)
736 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
738 mmf_return_if_fail(hcamcorder);
740 _mmcam_dbg_log("START");
742 _mmcam_dbg_log("Signal SEND");
743 pthread_cond_broadcast(&(hcamcorder->sound_cond));
745 _mmcam_dbg_log("DONE");