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>
27 #include <audio-session-manager.h>
28 #include "mm_camcorder_internal.h"
29 #include "mm_camcorder_sound.h"
31 /*---------------------------------------------------------------------------------------
32 | GLOBAL VARIABLE DEFINITIONS for internal |
33 ---------------------------------------------------------------------------------------*/
35 /*---------------------------------------------------------------------------------------
36 | LOCAL VARIABLE DEFINITIONS for internal |
37 ---------------------------------------------------------------------------------------*/
38 #define SAMPLE_SOUND_RATE 44100
39 #define DEFAULT_ACTIVE_DEVICE 0xffffffff
41 /*---------------------------------------------------------------------------------------
42 | LOCAL FUNCTION PROTOTYPES: |
43 ---------------------------------------------------------------------------------------*/
44 static void __solo_sound_callback(void *data);
46 static void __pulseaudio_play_sample_cb(pa_context *pulse_context, uint32_t stream_index, void *user_data)
48 SOUND_INFO *info = NULL;
50 mmf_return_if_fail(user_data);
52 info = (SOUND_INFO *)user_data;
54 _mmcam_dbg_log("START - idx : %d", stream_index);
56 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
58 _mmcam_dbg_log("DONE");
63 static void __pulseaudio_context_state_cb(pa_context *pulse_context, void *user_data)
66 SOUND_INFO *info = NULL;
68 mmf_return_if_fail(user_data);
70 info = (SOUND_INFO *)user_data;
72 state = pa_context_get_state(pulse_context);
74 case PA_CONTEXT_READY:
75 _mmcam_dbg_log("pulseaudio context READY");
76 if (info->pulse_context == pulse_context) {
78 _mmcam_dbg_log("pulseaudio send signal");
79 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
82 case PA_CONTEXT_TERMINATED:
83 if (info->pulse_context == pulse_context) {
85 _mmcam_dbg_log("Context terminated : pulseaudio send signal");
86 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
89 case PA_CONTEXT_UNCONNECTED:
90 case PA_CONTEXT_CONNECTING:
91 case PA_CONTEXT_AUTHORIZING:
92 case PA_CONTEXT_SETTING_NAME:
93 case PA_CONTEXT_FAILED:
95 _mmcam_dbg_log("pulseaudio context %p, state %d",
96 pulse_context, state);
103 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
104 static void __pulseaudio_stream_write_cb(pa_stream *stream, size_t length, void *user_data)
106 sf_count_t read_length;
108 SOUND_INFO *info = NULL;
110 mmf_return_if_fail(user_data);
112 info = (SOUND_INFO *)user_data;
114 _mmcam_dbg_log("START");
116 data = pa_xmalloc(length);
118 read_length = (sf_count_t)(length/pa_frame_size(&(info->sample_spec)));
120 if ((sf_readf_short(info->infile, data, read_length)) != read_length) {
125 pa_stream_write(stream, data, length, pa_xfree, 0, PA_SEEK_RELATIVE);
127 info->sample_length -= length;
129 if (info->sample_length <= 0) {
130 pa_stream_set_write_callback(info->sample_stream, NULL, NULL);
131 pa_stream_finish_upload(info->sample_stream);
133 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
134 _mmcam_dbg_log("send signal DONE");
137 _mmcam_dbg_log("DONE read_length %d", read_length);
143 static void __pulseaudio_remove_sample_finish_cb(pa_context *pulse_context, int success, void *user_data)
145 SOUND_INFO *info = NULL;
147 mmf_return_if_fail(user_data);
149 info = (SOUND_INFO *)user_data;
151 _mmcam_dbg_log("START");
153 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
155 _mmcam_dbg_log("DONE");
159 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
161 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
162 gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename)
163 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
164 gboolean _mmcamcorder_sound_init(MMHandleType handle)
165 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
168 int sound_enable = TRUE;
169 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
170 SOUND_INFO *info = NULL;
171 mm_sound_device_in device_in;
172 mm_sound_device_out device_out;
173 pa_mainloop_api *api = NULL;
174 int error = PA_ERR_INTERNAL;
176 mmf_return_val_if_fail(hcamcorder, FALSE);
178 /* check sound play enable */
179 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
180 "capture-sound-enable", &sound_enable,
182 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
184 _mmcam_dbg_warn("capture sound disabled");
188 info = &(hcamcorder->snd_info);
190 pthread_mutex_lock(&(info->open_mutex));
192 if (info->state > _MMCAMCORDER_SOUND_STATE_NONE) {
193 _mmcam_dbg_warn("already initialized [%d]", info->state);
194 pthread_mutex_unlock(&(info->open_mutex));
198 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
199 if (info->filename) {
200 free(info->filename);
201 info->filename = NULL;
204 info->filename = strdup(filename);
205 if (info->filename == NULL) {
206 _mmcam_dbg_err("strdup failed");
209 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
211 pthread_mutex_init(&(info->play_mutex), NULL);
212 pthread_cond_init(&(info->play_cond), NULL);
214 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
216 memset (&(info->sfinfo), 0, sizeof(SF_INFO));
217 info->infile = sf_open(info->filename, SFM_READ, &(info->sfinfo));
218 if (!(info->infile)) {
219 _mmcam_dbg_err("Failed to open sound file");
220 goto SOUND_INIT_ERROR;
222 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
225 * Init Pulseaudio thread
227 /* create pulseaudio mainloop */
228 info->pulse_mainloop = pa_threaded_mainloop_new();
229 if (info->pulse_mainloop == NULL) {
230 _mmcam_dbg_err("pa_threaded_mainloop_new failed");
231 goto SOUND_INIT_ERROR;
234 /* start PA mainloop */
235 ret = pa_threaded_mainloop_start(info->pulse_mainloop);
237 _mmcam_dbg_err("pa_threaded_mainloop_start failed");
238 goto SOUND_INIT_ERROR;
241 /* lock pulseaudio thread */
242 pa_threaded_mainloop_lock(info->pulse_mainloop);
244 /* get pulseaudio api */
245 api = pa_threaded_mainloop_get_api(info->pulse_mainloop);
247 _mmcam_dbg_err("pa_threaded_mainloop_get_api failed");
248 pa_threaded_mainloop_unlock(info->pulse_mainloop);
249 goto SOUND_INIT_ERROR;
252 /* create pulseaudio context */
253 info->pulse_context = pa_context_new(api, NULL);
254 if (info->pulse_context == NULL) {
255 _mmcam_dbg_err("pa_context_new failed");
256 pa_threaded_mainloop_unlock(info->pulse_mainloop);
257 goto SOUND_INIT_ERROR;
260 /* set pulseaudio context callback */
261 pa_context_set_state_callback(info->pulse_context, __pulseaudio_context_state_cb, info);
263 if (pa_context_connect(info->pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
264 _mmcam_dbg_err("pa_context_connect error");
267 /* wait READY state of pulse context */
269 pa_context_state_t state = pa_context_get_state(info->pulse_context);
271 _mmcam_dbg_log("pa context state is now %d", state);
273 if (!PA_CONTEXT_IS_GOOD (state)) {
274 _mmcam_dbg_log("connection failed");
278 if (state == PA_CONTEXT_READY) {
279 _mmcam_dbg_log("pa context READY");
283 /* Wait until the context is ready */
284 _mmcam_dbg_log("waiting..................");
285 pa_threaded_mainloop_wait(info->pulse_mainloop);
286 _mmcam_dbg_log("waiting DONE. check again...");
289 /* unlock pulseaudio thread */
290 pa_threaded_mainloop_unlock(info->pulse_mainloop);
292 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
296 if (pa_sndfile_read_sample_spec(info->infile, &(info->sample_spec)) < 0) {
297 _mmcam_dbg_err("Failed to determine sample specification from file");
298 goto SOUND_INIT_ERROR;
301 info->sample_spec.format = PA_SAMPLE_S16LE;
303 if (pa_sndfile_read_channel_map(info->infile, &(info->channel_map)) < 0) {
304 pa_channel_map_init_extend(&(info->channel_map), info->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
306 if (info->sample_spec.channels > 2) {
307 _mmcam_dbg_warn("Failed to determine sample specification from file");
311 info->sample_length = (size_t)info->sfinfo.frames * pa_frame_size(&(info->sample_spec));
313 pa_threaded_mainloop_lock(info->pulse_mainloop);
315 /* prepare uploading */
316 info->sample_stream = pa_stream_new(info->pulse_context, SAMPLE_SOUND_NAME, &(info->sample_spec), NULL);
317 /* set stream write callback */
318 pa_stream_set_write_callback(info->sample_stream, __pulseaudio_stream_write_cb, info);
319 /* upload sample (ASYNC) */
320 pa_stream_connect_upload(info->sample_stream, info->sample_length);
321 /* wait for upload completion */
322 pa_threaded_mainloop_wait(info->pulse_mainloop);
324 pa_threaded_mainloop_unlock(info->pulse_mainloop);
327 sf_close(info->infile);
329 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
330 if (info->sample_stream) {
331 pa_stream_connect_playback(info->sample_stream, NULL, NULL, 0, NULL, NULL);
334 pa_stream_state_t state = pa_stream_get_state(info->sample_stream);
336 if (state == PA_STREAM_READY) {
337 _mmcam_dbg_warn("device READY done");
341 if (!PA_STREAM_IS_GOOD(state)) {
342 error = pa_context_errno(info->pulse_context);
343 _mmcam_dbg_err("pa context state is not good, %d", error);
347 /* Wait until the stream is ready */
348 pa_threaded_mainloop_wait(info->pulse_mainloop);
351 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
353 /* backup current route */
354 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
356 ret = mm_sound_get_active_device(&device_in, &device_out);
357 if (ret != MM_ERROR_NONE) {
358 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]. skip sound play.", ret);
359 goto SOUND_INIT_ERROR;
362 _mmcam_dbg_log("current out [%x]", device_out);
364 if (device_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
365 //ret = mm_sound_set_active_route_without_broadcast (MM_SOUND_ROUTE_OUT_SPEAKER);
366 if (ret != MM_ERROR_NONE) {
367 _mmcam_dbg_err("mm_sound_set_active_route_without_broadcast failed [%x]. skip sound play.", ret);
368 goto SOUND_INIT_ERROR;
370 info->active_out_backup = device_out;
373 //info->volume_type = PA_TIZEN_AUDIO_VOLUME_TYPE_FIXED;
374 info->volume_level = 0;
376 info->state = _MMCAMCORDER_SOUND_STATE_INIT;
378 _mmcam_dbg_log("init DONE");
380 pthread_mutex_unlock(&(info->open_mutex));
386 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
388 * Release allocated resources
390 if (info->filename) {
391 free(info->filename);
392 info->filename = NULL;
394 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
396 /* remove pulse mainloop */
397 if (info->pulse_mainloop) {
398 pa_threaded_mainloop_lock(info->pulse_mainloop);
400 /* remove pulse context */
401 if (info->pulse_context) {
402 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
403 /* remove uploaded sample */
404 if (info->sample_stream) {
405 pa_threaded_mainloop_lock(info->pulse_mainloop);
407 /* Remove sample (ASYNC) */
408 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
410 /* Wait for async operation */
411 pa_threaded_mainloop_wait(info->pulse_mainloop);
413 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
414 /* release sample stream */
415 if (info->sample_stream) {
416 pa_stream_disconnect(info->sample_stream);
417 pa_stream_unref(info->sample_stream);
418 info->sample_stream = NULL;
420 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
422 /* Make sure we don't get any further callbacks */
423 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
425 pa_context_disconnect(info->pulse_context);
426 pa_context_unref(info->pulse_context);
427 info->pulse_context = NULL;
430 pa_threaded_mainloop_unlock(info->pulse_mainloop);
432 pa_threaded_mainloop_stop(info->pulse_mainloop);
433 pa_threaded_mainloop_free(info->pulse_mainloop);
434 info->pulse_mainloop = NULL;
437 /* remove mutex and cond */
438 pthread_mutex_destroy(&(info->play_mutex));
439 pthread_cond_destroy(&(info->play_cond));
441 pthread_mutex_unlock(&(info->open_mutex));
447 gboolean _mmcamcorder_sound_play(MMHandleType handle, const char *sample_name, gboolean sync_play)
449 int sound_enable = TRUE;
450 int gain_type = VOLUME_GAIN_SHUTTER1;
452 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
453 SOUND_INFO *info = NULL;
454 pa_operation *pulse_op = NULL;
456 mmf_return_val_if_fail(hcamcorder && sample_name, FALSE);
458 /* check sound play enable */
459 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
460 "capture-sound-enable", &sound_enable,
462 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
464 _mmcam_dbg_warn("capture sound disabled");
468 info = &(hcamcorder->snd_info);
470 pthread_mutex_lock(&(info->open_mutex));
472 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
473 _mmcam_dbg_log("not initialized state:[%d]", info->state);
474 pthread_mutex_unlock(&(info->open_mutex));
478 if (!strcmp(sample_name, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE)) {
479 gain_type = VOLUME_GAIN_SHUTTER2;
480 } else if (!strcmp(sample_name, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP)) {
481 gain_type = VOLUME_GAIN_CAMCORDING;
484 _mmcam_dbg_log("Play start - sample name [%s]", sample_name);
487 pa_threaded_mainloop_lock(info->pulse_mainloop);
489 pulse_op = pa_ext_policy_play_sample(info->pulse_context,
494 __pulseaudio_play_sample_cb,
497 _mmcam_dbg_log("wait for signal");
498 pa_threaded_mainloop_wait(info->pulse_mainloop);
499 _mmcam_dbg_log("received signal");
501 pa_threaded_mainloop_unlock(info->pulse_mainloop);
504 pulse_op = pa_ext_policy_play_sample(info->pulse_context,
514 pa_operation_unref(pulse_op);
518 pthread_mutex_unlock(&(info->open_mutex));
520 _mmcam_dbg_log("Done");
526 gboolean _mmcamcorder_sound_finalize(MMHandleType handle)
528 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
529 SOUND_INFO *info = NULL;
530 mm_sound_device_in device_in;
531 mm_sound_device_out device_out;
534 mmf_return_val_if_fail(hcamcorder, FALSE);
536 info = &(hcamcorder->snd_info);
538 _mmcam_dbg_err("START");
540 pthread_mutex_lock(&(info->open_mutex));
542 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
543 _mmcam_dbg_warn("not initialized");
544 pthread_mutex_unlock(&(info->open_mutex));
549 _mmcam_dbg_log("restore route");
550 if (info->active_out_backup != DEFAULT_ACTIVE_DEVICE) {
551 ret = mm_sound_get_active_device(&device_in, &device_out);
552 if (ret != MM_ERROR_NONE) {
553 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]", ret);
556 _mmcam_dbg_log("current out [%x]", device_out);
558 if (device_out != info->active_out_backup) {
559 //ret = mm_sound_set_active_route_without_broadcast (info->active_out_backup);
560 if (ret != MM_ERROR_NONE) {
561 _mmcam_dbg_err("mm_sound_set_active_route_without_broadcast [%x]", ret);
566 pa_threaded_mainloop_lock(info->pulse_mainloop);
568 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
572 _mmcam_dbg_log("remove sample");
574 /* Remove sample (ASYNC) */
575 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
577 /* Wait for async operation */
578 pa_threaded_mainloop_wait(info->pulse_mainloop);
579 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
580 if (info->sample_stream) {
581 pa_stream_disconnect(info->sample_stream);
582 pa_stream_unref(info->sample_stream);
583 info->sample_stream = NULL;
585 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
588 * Release pulseaudio thread
590 _mmcam_dbg_log("release pulseaudio thread");
592 pa_context_disconnect(info->pulse_context);
594 /* Make sure we don't get any further callbacks */
595 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
597 pa_context_unref(info->pulse_context);
598 info->pulse_context = NULL;
600 pa_threaded_mainloop_unlock(info->pulse_mainloop);
602 pa_threaded_mainloop_stop(info->pulse_mainloop);
603 pa_threaded_mainloop_free(info->pulse_mainloop);
604 info->pulse_mainloop = NULL;
606 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
607 if (info->filename) {
608 free(info->filename);
609 info->filename = NULL;
611 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
613 info->state = _MMCAMCORDER_SOUND_STATE_NONE;
614 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
616 /* release mutex and cond */
617 _mmcam_dbg_log("release play_mutex/cond");
618 pthread_mutex_destroy(&(info->play_mutex));
619 pthread_cond_destroy(&(info->play_cond));
621 pthread_mutex_unlock(&(info->open_mutex));
623 _mmcam_dbg_err("DONE");
629 void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gboolean sync_play)
631 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
633 int sound_handle = 0;
634 int ret = MM_ERROR_NONE;
635 int sound_enable = TRUE;
636 int sound_played = FALSE;
637 int gain_type = VOLUME_GAIN_SHUTTER1;
639 mmf_return_if_fail(filepath && hcamcorder);
641 _mmcam_dbg_log("START : %s", filepath);
643 _mmcamcorder_sound_solo_play_wait(handle);
645 ret = pthread_mutex_trylock(&(hcamcorder->sound_lock));
647 _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret));
651 /* check filename to set gain_type */
652 if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE_SND) ||
653 !strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_START_SND)) {
654 if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_START_SND)) {
655 gain_type = VOLUME_GAIN_CAMCORDING;
657 gain_type = VOLUME_GAIN_SHUTTER1;
659 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE2_SND)) {
660 gain_type = VOLUME_GAIN_SHUTTER2;
661 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_STOP_SND)) {
662 gain_type = VOLUME_GAIN_CAMCORDING;
665 _mmcam_dbg_log("gain type 0x%x", gain_type);
667 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
668 "capture-sound-enable", &sound_enable,
670 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
673 /* send capture sound completed message */
674 pthread_mutex_unlock(&(hcamcorder->sound_lock));
679 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON ||
680 hcamcorder->sub_context->info_image->sound_status) {
681 ret = mm_sound_play_loud_solo_sound(filepath, VOLUME_TYPE_FIXED | gain_type,
682 (mm_sound_stop_callback_func)__solo_sound_callback, (void*)hcamcorder, &sound_handle);
685 _mmcam_dbg_warn("skip shutter sound");
688 _mmcam_dbg_log("sync_play %d, sound_played %d, ret 0x%x", sync_play, sound_played, ret);
690 if (ret != MM_ERROR_NONE) {
691 _mmcam_dbg_err( "Capture sound play FAILED.[%x]", ret );
694 /* increase capture sound count */
695 hcamcorder->capture_sound_count++;
698 /* wait for sound completed signal */
699 if (sync_play && sound_played) {
700 struct timespec timeout;
703 gettimeofday( &tv, NULL );
704 timeout.tv_sec = tv.tv_sec + 2;
705 timeout.tv_nsec = tv.tv_usec * 1000;
707 _mmcam_dbg_log("Wait for signal");
709 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
710 _mmcam_dbg_log("signal received.");
712 _mmcam_dbg_warn("capture sound play timeout.");
713 if (sound_handle > 0) {
714 mm_sound_stop_sound(sound_handle);
720 pthread_mutex_unlock(&(hcamcorder->sound_lock));
722 _mmcam_dbg_log("DONE");
727 static void __solo_sound_callback(void *data)
729 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
731 mmf_return_if_fail(hcamcorder);
733 _mmcam_dbg_log("START");
735 /* decrease capture sound count */
736 pthread_mutex_lock(&(hcamcorder->sound_lock));
737 if (hcamcorder->capture_sound_count > 0) {
738 hcamcorder->capture_sound_count--;
740 _mmcam_dbg_warn("invalid capture_sound_count %d, reset count", hcamcorder->capture_sound_count);
741 hcamcorder->capture_sound_count = 0;
743 pthread_mutex_unlock(&(hcamcorder->sound_lock));
745 _mmcam_dbg_log("Signal SEND");
746 pthread_cond_broadcast(&(hcamcorder->sound_cond));
748 _mmcam_dbg_log("DONE");
754 void _mmcamcorder_sound_solo_play_wait(MMHandleType handle)
756 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
758 mmf_return_if_fail(hcamcorder);
760 _mmcam_dbg_log("START");
762 /* check playing sound count */
763 pthread_mutex_lock(&(hcamcorder->sound_lock));
764 if (hcamcorder->capture_sound_count > 0) {
765 struct timespec timeout;
768 gettimeofday( &tv, NULL );
769 timeout.tv_sec = tv.tv_sec + 2;
770 timeout.tv_nsec = tv.tv_usec * 1000;
772 _mmcam_dbg_log("Wait for signal");
774 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
775 _mmcam_dbg_log("signal received.");
777 _mmcam_dbg_warn("capture sound play timeout.");
780 _mmcam_dbg_warn("no playing sound - count %d", hcamcorder->capture_sound_count);
782 pthread_mutex_unlock(&(hcamcorder->sound_lock));
784 _mmcam_dbg_log("DONE");