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 "mm_camcorder_internal.h"
28 #include "mm_camcorder_sound.h"
30 /*---------------------------------------------------------------------------------------
31 | GLOBAL VARIABLE DEFINITIONS for internal |
32 ---------------------------------------------------------------------------------------*/
34 /*---------------------------------------------------------------------------------------
35 | LOCAL VARIABLE DEFINITIONS for internal |
36 ---------------------------------------------------------------------------------------*/
37 #define SAMPLE_SOUND_RATE 44100
38 #define DEFAULT_ACTIVE_DEVICE 0xffffffff
40 /*---------------------------------------------------------------------------------------
41 | LOCAL FUNCTION PROTOTYPES: |
42 ---------------------------------------------------------------------------------------*/
43 static void __solo_sound_callback(void *data);
45 static void __pulseaudio_play_sample_cb(pa_context *pulse_context, uint32_t stream_index, void *user_data)
47 SOUND_INFO *info = NULL;
49 mmf_return_if_fail(user_data);
51 info = (SOUND_INFO *)user_data;
53 _mmcam_dbg_log("START - idx : %d", stream_index);
55 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
57 _mmcam_dbg_log("DONE");
62 static void __pulseaudio_context_state_cb(pa_context *pulse_context, void *user_data)
65 SOUND_INFO *info = NULL;
67 mmf_return_if_fail(user_data);
69 info = (SOUND_INFO *)user_data;
71 state = pa_context_get_state(pulse_context);
73 case PA_CONTEXT_READY:
74 _mmcam_dbg_log("pulseaudio context READY");
75 if (info->pulse_context == pulse_context) {
77 _mmcam_dbg_log("pulseaudio send signal");
78 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
81 case PA_CONTEXT_TERMINATED:
82 if (info->pulse_context == pulse_context) {
84 _mmcam_dbg_log("Context terminated : pulseaudio send signal");
85 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
88 case PA_CONTEXT_UNCONNECTED:
89 case PA_CONTEXT_CONNECTING:
90 case PA_CONTEXT_AUTHORIZING:
91 case PA_CONTEXT_SETTING_NAME:
92 case PA_CONTEXT_FAILED:
94 _mmcam_dbg_log("pulseaudio context %p, state %d",
95 pulse_context, state);
102 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
103 static void __pulseaudio_stream_write_cb(pa_stream *stream, size_t length, void *user_data)
105 sf_count_t read_length;
107 SOUND_INFO *info = NULL;
109 mmf_return_if_fail(user_data);
111 info = (SOUND_INFO *)user_data;
113 _mmcam_dbg_log("START");
115 data = pa_xmalloc(length);
117 read_length = (sf_count_t)(length/pa_frame_size(&(info->sample_spec)));
119 if ((sf_readf_short(info->infile, data, read_length)) != read_length) {
124 pa_stream_write(stream, data, length, pa_xfree, 0, PA_SEEK_RELATIVE);
126 info->sample_length -= length;
128 if (info->sample_length <= 0) {
129 pa_stream_set_write_callback(info->sample_stream, NULL, NULL);
130 pa_stream_finish_upload(info->sample_stream);
132 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
133 _mmcam_dbg_log("send signal DONE");
136 _mmcam_dbg_log("DONE read_length %d", read_length);
142 static void __pulseaudio_remove_sample_finish_cb(pa_context *pulse_context, int success, void *user_data)
144 SOUND_INFO *info = NULL;
146 mmf_return_if_fail(user_data);
148 info = (SOUND_INFO *)user_data;
150 _mmcam_dbg_log("START");
152 pa_threaded_mainloop_signal(info->pulse_mainloop, 0);
154 _mmcam_dbg_log("DONE");
158 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
160 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
161 gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename)
162 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
163 gboolean _mmcamcorder_sound_init(MMHandleType handle)
164 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
167 int sound_enable = TRUE;
168 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
169 SOUND_INFO *info = NULL;
170 mm_sound_device_in device_in;
171 mm_sound_device_out device_out;
172 pa_mainloop_api *api = NULL;
173 int error = PA_ERR_INTERNAL;
175 mmf_return_val_if_fail(hcamcorder, FALSE);
177 /* check sound play enable */
178 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
179 "capture-sound-enable", &sound_enable,
181 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
183 _mmcam_dbg_warn("capture sound disabled");
187 info = &(hcamcorder->snd_info);
189 pthread_mutex_lock(&(info->open_mutex));
191 if (info->state > _MMCAMCORDER_SOUND_STATE_NONE) {
192 _mmcam_dbg_warn("already initialized [%d]", info->state);
193 pthread_mutex_unlock(&(info->open_mutex));
197 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
198 if (info->filename) {
199 free(info->filename);
200 info->filename = NULL;
203 info->filename = strdup(filename);
204 if (info->filename == NULL) {
205 _mmcam_dbg_err("strdup failed");
208 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
210 pthread_mutex_init(&(info->play_mutex), NULL);
211 pthread_cond_init(&(info->play_cond), NULL);
213 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
215 memset (&(info->sfinfo), 0, sizeof(SF_INFO));
216 info->infile = sf_open(info->filename, SFM_READ, &(info->sfinfo));
217 if (!(info->infile)) {
218 _mmcam_dbg_err("Failed to open sound file");
219 goto SOUND_INIT_ERROR;
221 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
224 * Init Pulseaudio thread
226 /* create pulseaudio mainloop */
227 info->pulse_mainloop = pa_threaded_mainloop_new();
228 if (info->pulse_mainloop == NULL) {
229 _mmcam_dbg_err("pa_threaded_mainloop_new failed");
230 goto SOUND_INIT_ERROR;
233 /* start PA mainloop */
234 ret = pa_threaded_mainloop_start(info->pulse_mainloop);
236 _mmcam_dbg_err("pa_threaded_mainloop_start failed");
237 goto SOUND_INIT_ERROR;
240 /* lock pulseaudio thread */
241 pa_threaded_mainloop_lock(info->pulse_mainloop);
243 /* get pulseaudio api */
244 api = pa_threaded_mainloop_get_api(info->pulse_mainloop);
246 _mmcam_dbg_err("pa_threaded_mainloop_get_api failed");
247 pa_threaded_mainloop_unlock(info->pulse_mainloop);
248 goto SOUND_INIT_ERROR;
251 /* create pulseaudio context */
252 info->pulse_context = pa_context_new(api, NULL);
253 if (info->pulse_context == NULL) {
254 _mmcam_dbg_err("pa_context_new failed");
255 pa_threaded_mainloop_unlock(info->pulse_mainloop);
256 goto SOUND_INIT_ERROR;
259 /* set pulseaudio context callback */
260 pa_context_set_state_callback(info->pulse_context, __pulseaudio_context_state_cb, info);
262 if (pa_context_connect(info->pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
263 _mmcam_dbg_err("pa_context_connect error");
266 /* wait READY state of pulse context */
268 pa_context_state_t state = pa_context_get_state(info->pulse_context);
270 _mmcam_dbg_log("pa context state is now %d", state);
272 if (!PA_CONTEXT_IS_GOOD (state)) {
273 _mmcam_dbg_log("connection failed");
277 if (state == PA_CONTEXT_READY) {
278 _mmcam_dbg_log("pa context READY");
282 /* Wait until the context is ready */
283 _mmcam_dbg_log("waiting..................");
284 pa_threaded_mainloop_wait(info->pulse_mainloop);
285 _mmcam_dbg_log("waiting DONE. check again...");
288 /* unlock pulseaudio thread */
289 pa_threaded_mainloop_unlock(info->pulse_mainloop);
291 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
295 if (pa_sndfile_read_sample_spec(info->infile, &(info->sample_spec)) < 0) {
296 _mmcam_dbg_err("Failed to determine sample specification from file");
297 goto SOUND_INIT_ERROR;
300 info->sample_spec.format = PA_SAMPLE_S16LE;
302 if (pa_sndfile_read_channel_map(info->infile, &(info->channel_map)) < 0) {
303 pa_channel_map_init_extend(&(info->channel_map), info->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
305 if (info->sample_spec.channels > 2) {
306 _mmcam_dbg_warn("Failed to determine sample specification from file");
310 info->sample_length = (size_t)info->sfinfo.frames * pa_frame_size(&(info->sample_spec));
312 pa_threaded_mainloop_lock(info->pulse_mainloop);
314 /* prepare uploading */
315 info->sample_stream = pa_stream_new(info->pulse_context, SAMPLE_SOUND_NAME, &(info->sample_spec), NULL);
316 /* set stream write callback */
317 pa_stream_set_write_callback(info->sample_stream, __pulseaudio_stream_write_cb, info);
318 /* upload sample (ASYNC) */
319 pa_stream_connect_upload(info->sample_stream, info->sample_length);
320 /* wait for upload completion */
321 pa_threaded_mainloop_wait(info->pulse_mainloop);
323 pa_threaded_mainloop_unlock(info->pulse_mainloop);
326 sf_close(info->infile);
328 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
329 if (info->sample_stream) {
330 pa_stream_connect_playback(info->sample_stream, NULL, NULL, 0, NULL, NULL);
333 pa_stream_state_t state = pa_stream_get_state(info->sample_stream);
335 if (state == PA_STREAM_READY) {
336 _mmcam_dbg_warn("device READY done");
340 if (!PA_STREAM_IS_GOOD(state)) {
341 error = pa_context_errno(info->pulse_context);
342 _mmcam_dbg_err("pa context state is not good, %d", error);
346 /* Wait until the stream is ready */
347 pa_threaded_mainloop_wait(info->pulse_mainloop);
350 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
352 /* backup current route */
353 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
355 ret = mm_sound_get_active_device(&device_in, &device_out);
356 if (ret != MM_ERROR_NONE) {
357 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]. skip sound play.", ret);
358 goto SOUND_INIT_ERROR;
361 _mmcam_dbg_log("current out [%x]", device_out);
363 if (device_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
364 //ret = mm_sound_set_active_route_without_broadcast (MM_SOUND_ROUTE_OUT_SPEAKER);
365 if (ret != MM_ERROR_NONE) {
366 _mmcam_dbg_err("mm_sound_set_active_route_without_broadcast failed [%x]. skip sound play.", ret);
367 goto SOUND_INIT_ERROR;
369 info->active_out_backup = device_out;
372 //info->volume_type = PA_TIZEN_AUDIO_VOLUME_TYPE_FIXED;
373 info->volume_level = 0;
375 info->state = _MMCAMCORDER_SOUND_STATE_INIT;
377 _mmcam_dbg_log("init DONE");
379 pthread_mutex_unlock(&(info->open_mutex));
385 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
387 * Release allocated resources
389 if (info->filename) {
390 free(info->filename);
391 info->filename = NULL;
393 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
395 /* remove pulse mainloop */
396 if (info->pulse_mainloop) {
397 pa_threaded_mainloop_lock(info->pulse_mainloop);
399 /* remove pulse context */
400 if (info->pulse_context) {
401 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
402 /* remove uploaded sample */
403 if (info->sample_stream) {
404 pa_threaded_mainloop_lock(info->pulse_mainloop);
406 /* Remove sample (ASYNC) */
407 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
409 /* Wait for async operation */
410 pa_threaded_mainloop_wait(info->pulse_mainloop);
412 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
413 /* release sample stream */
414 if (info->sample_stream) {
415 pa_stream_disconnect(info->sample_stream);
416 pa_stream_unref(info->sample_stream);
417 info->sample_stream = NULL;
419 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
421 /* Make sure we don't get any further callbacks */
422 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
424 pa_context_disconnect(info->pulse_context);
425 pa_context_unref(info->pulse_context);
426 info->pulse_context = NULL;
429 pa_threaded_mainloop_unlock(info->pulse_mainloop);
431 pa_threaded_mainloop_stop(info->pulse_mainloop);
432 pa_threaded_mainloop_free(info->pulse_mainloop);
433 info->pulse_mainloop = NULL;
436 /* remove mutex and cond */
437 pthread_mutex_destroy(&(info->play_mutex));
438 pthread_cond_destroy(&(info->play_cond));
440 pthread_mutex_unlock(&(info->open_mutex));
446 gboolean _mmcamcorder_sound_play(MMHandleType handle, const char *sample_name, gboolean sync_play)
448 int sound_enable = TRUE;
449 int gain_type = VOLUME_GAIN_SHUTTER1;
451 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
452 SOUND_INFO *info = NULL;
453 pa_operation *pulse_op = NULL;
455 mmf_return_val_if_fail(hcamcorder && sample_name, FALSE);
457 /* check sound play enable */
458 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
459 "capture-sound-enable", &sound_enable,
461 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
463 _mmcam_dbg_warn("capture sound disabled");
467 info = &(hcamcorder->snd_info);
469 pthread_mutex_lock(&(info->open_mutex));
471 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
472 _mmcam_dbg_log("not initialized state:[%d]", info->state);
473 pthread_mutex_unlock(&(info->open_mutex));
477 if (!strcmp(sample_name, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE)) {
478 gain_type = VOLUME_GAIN_SHUTTER2;
479 } else if (!strcmp(sample_name, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP)) {
480 gain_type = VOLUME_GAIN_CAMCORDING;
483 _mmcam_dbg_log("Play start - sample name [%s]", sample_name);
486 pa_threaded_mainloop_lock(info->pulse_mainloop);
488 pulse_op = pa_ext_policy_play_sample(info->pulse_context,
493 __pulseaudio_play_sample_cb,
496 _mmcam_dbg_log("wait for signal");
497 pa_threaded_mainloop_wait(info->pulse_mainloop);
498 _mmcam_dbg_log("received signal");
500 pa_threaded_mainloop_unlock(info->pulse_mainloop);
503 pulse_op = pa_ext_policy_play_sample(info->pulse_context,
513 pa_operation_unref(pulse_op);
517 pthread_mutex_unlock(&(info->open_mutex));
519 _mmcam_dbg_log("Done");
525 gboolean _mmcamcorder_sound_finalize(MMHandleType handle)
527 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
528 SOUND_INFO *info = NULL;
529 mm_sound_device_in device_in;
530 mm_sound_device_out device_out;
533 mmf_return_val_if_fail(hcamcorder, FALSE);
535 info = &(hcamcorder->snd_info);
537 _mmcam_dbg_err("START");
539 pthread_mutex_lock(&(info->open_mutex));
541 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
542 _mmcam_dbg_warn("not initialized");
543 pthread_mutex_unlock(&(info->open_mutex));
548 _mmcam_dbg_log("restore route");
549 if (info->active_out_backup != DEFAULT_ACTIVE_DEVICE) {
550 ret = mm_sound_get_active_device(&device_in, &device_out);
551 if (ret != MM_ERROR_NONE) {
552 _mmcam_dbg_err("mm_sound_get_active_device failed [%x]", ret);
555 _mmcam_dbg_log("current out [%x]", device_out);
557 if (device_out != info->active_out_backup) {
558 //ret = mm_sound_set_active_route_without_broadcast (info->active_out_backup);
559 if (ret != MM_ERROR_NONE) {
560 _mmcam_dbg_err("mm_sound_set_active_route_without_broadcast [%x]", ret);
565 pa_threaded_mainloop_lock(info->pulse_mainloop);
567 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
571 _mmcam_dbg_log("remove sample");
573 /* Remove sample (ASYNC) */
574 pa_operation_unref(pa_context_remove_sample(info->pulse_context, SAMPLE_SOUND_NAME, __pulseaudio_remove_sample_finish_cb, info));
576 /* Wait for async operation */
577 pa_threaded_mainloop_wait(info->pulse_mainloop);
578 #else /* _MMCAMCORDER_UPLOAD_SAMPLE */
579 if (info->sample_stream) {
580 pa_stream_disconnect(info->sample_stream);
581 pa_stream_unref(info->sample_stream);
582 info->sample_stream = NULL;
584 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
587 * Release pulseaudio thread
589 _mmcam_dbg_log("release pulseaudio thread");
591 pa_context_disconnect(info->pulse_context);
593 /* Make sure we don't get any further callbacks */
594 pa_context_set_state_callback(info->pulse_context, NULL, NULL);
596 pa_context_unref(info->pulse_context);
597 info->pulse_context = NULL;
599 pa_threaded_mainloop_unlock(info->pulse_mainloop);
601 pa_threaded_mainloop_stop(info->pulse_mainloop);
602 pa_threaded_mainloop_free(info->pulse_mainloop);
603 info->pulse_mainloop = NULL;
605 #ifdef _MMCAMCORDER_UPLOAD_SAMPLE
606 if (info->filename) {
607 free(info->filename);
608 info->filename = NULL;
610 #endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
612 info->state = _MMCAMCORDER_SOUND_STATE_NONE;
613 info->active_out_backup = DEFAULT_ACTIVE_DEVICE;
615 /* release mutex and cond */
616 _mmcam_dbg_log("release play_mutex/cond");
617 pthread_mutex_destroy(&(info->play_mutex));
618 pthread_cond_destroy(&(info->play_cond));
620 pthread_mutex_unlock(&(info->open_mutex));
622 _mmcam_dbg_err("DONE");
628 void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gboolean sync_play)
630 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
632 int sound_handle = 0;
633 int ret = MM_ERROR_NONE;
634 int sound_enable = TRUE;
635 int sound_played = FALSE;
636 int gain_type = VOLUME_GAIN_SHUTTER1;
638 mmf_return_if_fail(filepath && hcamcorder);
640 _mmcam_dbg_log("START : %s", filepath);
642 _mmcamcorder_sound_solo_play_wait(handle);
644 ret = pthread_mutex_trylock(&(hcamcorder->sound_lock));
646 _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret));
650 /* check filename to set gain_type */
651 if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE_SND) ||
652 !strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_START_SND)) {
653 if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_START_SND)) {
654 gain_type = VOLUME_GAIN_CAMCORDING;
656 gain_type = VOLUME_GAIN_SHUTTER1;
658 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_CAPTURE2_SND)) {
659 gain_type = VOLUME_GAIN_SHUTTER2;
660 } else if (!strcmp(filepath, _MMCAMCORDER_FILEPATH_REC_STOP_SND)) {
661 gain_type = VOLUME_GAIN_CAMCORDING;
664 _mmcam_dbg_log("gain type 0x%x", gain_type);
666 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
667 "capture-sound-enable", &sound_enable,
669 _mmcam_dbg_log("Capture sound enable %d", sound_enable);
672 /* send capture sound completed message */
673 pthread_mutex_unlock(&(hcamcorder->sound_lock));
678 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_ON ||
679 hcamcorder->sub_context->info_image->sound_status) {
680 ret = mm_sound_play_loud_solo_sound(filepath, VOLUME_TYPE_FIXED | gain_type,
681 (mm_sound_stop_callback_func)__solo_sound_callback, (void*)hcamcorder, &sound_handle);
684 _mmcam_dbg_warn("skip shutter sound");
687 _mmcam_dbg_log("sync_play %d, sound_played %d, ret 0x%x", sync_play, sound_played, ret);
689 if (ret != MM_ERROR_NONE) {
690 _mmcam_dbg_err( "Capture sound play FAILED.[%x]", ret );
693 /* increase capture sound count */
694 hcamcorder->capture_sound_count++;
697 /* wait for sound completed signal */
698 if (sync_play && sound_played) {
699 struct timespec timeout;
702 gettimeofday( &tv, NULL );
703 timeout.tv_sec = tv.tv_sec + 2;
704 timeout.tv_nsec = tv.tv_usec * 1000;
706 _mmcam_dbg_log("Wait for signal");
708 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
709 _mmcam_dbg_log("signal received.");
711 _mmcam_dbg_warn("capture sound play timeout.");
712 if (sound_handle > 0) {
713 mm_sound_stop_sound(sound_handle);
719 pthread_mutex_unlock(&(hcamcorder->sound_lock));
721 _mmcam_dbg_log("DONE");
726 static void __solo_sound_callback(void *data)
728 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
730 mmf_return_if_fail(hcamcorder);
732 _mmcam_dbg_log("START");
734 /* decrease capture sound count */
735 pthread_mutex_lock(&(hcamcorder->sound_lock));
736 if (hcamcorder->capture_sound_count > 0) {
737 hcamcorder->capture_sound_count--;
739 _mmcam_dbg_warn("invalid capture_sound_count %d, reset count", hcamcorder->capture_sound_count);
740 hcamcorder->capture_sound_count = 0;
742 pthread_mutex_unlock(&(hcamcorder->sound_lock));
744 _mmcam_dbg_log("Signal SEND");
745 pthread_cond_broadcast(&(hcamcorder->sound_cond));
747 _mmcam_dbg_log("DONE");
753 void _mmcamcorder_sound_solo_play_wait(MMHandleType handle)
755 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
757 mmf_return_if_fail(hcamcorder);
759 _mmcam_dbg_log("START");
761 /* check playing sound count */
762 pthread_mutex_lock(&(hcamcorder->sound_lock));
763 if (hcamcorder->capture_sound_count > 0) {
764 struct timespec timeout;
767 gettimeofday( &tv, NULL );
768 timeout.tv_sec = tv.tv_sec + 2;
769 timeout.tv_nsec = tv.tv_usec * 1000;
771 _mmcam_dbg_log("Wait for signal");
773 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
774 _mmcam_dbg_log("signal received.");
776 _mmcam_dbg_warn("capture sound play timeout.");
779 _mmcam_dbg_warn("no playing sound - count %d", hcamcorder->capture_sound_count);
781 pthread_mutex_unlock(&(hcamcorder->sound_lock));
783 _mmcam_dbg_log("DONE");