2 * Copyright (c) 2016 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.
17 /*==================================================================================================
19 ==================================================================================================*/
29 #include <sound_manager.h>
31 #include <feedback-internal.h>
34 #include <msg-manager-contact.h>
35 #include <msg-manager-debug.h>
36 #include <msg-manager-notification.h>
37 #include <msg-manager-sound.h>
38 #include <msg-manager-util.h>
40 /*==================================================================================================
42 ==================================================================================================*/
44 #define DEFAULT_ALERT_FILE TZ_SYS_RO_APP_PATH "/" MSG_SETTING_APP_ID "shared/res/settings/Alerts/General notification_sdk.wav"
46 #define MSG_MGR_SOUND_TIMEOUT 5500
49 /*==================================================================================================
51 ==================================================================================================*/
52 player_h g_PlayerHandle = NULL;
53 sound_stream_info_h g_stream_info = NULL;
54 char *defaultRingtonePath = NULL;
55 bool bFeedbackInit = false;
56 bool bPlaying = false;
58 pthread_mutex_t muMmPlay = PTHREAD_MUTEX_INITIALIZER;
59 pthread_mutex_t muStream = PTHREAD_MUTEX_INITIALIZER;
61 /*==================================================================================================
63 ===================================================================================================*/
64 int MsgMgrGetFileSize(const char *pFileName);
66 int MsgMgrStreamStart(MSG_MGR_SOUND_TYPE_T soundType);
67 void MsgMgrStreamStop();
68 void MsgMgrGetPlayStatus(bool bOnCall, bool bSound, bool bVibration, bool bMsgSound, bool bMsgVibration, bool *bPlaySound, bool *bPlayVibration);
70 void MsgMgrSoundPlayMelody(char *pMsgToneFilePath);
71 void MsgMgrSoundPlayVibration();
73 /*==================================================================================================
74 FUNCTION IMPLEMENTATION
75 ==================================================================================================*/
76 int MsgMgrGetFileSize(const char *pFileName)
78 struct stat file_stat;
80 if (lstat(pFileName, &file_stat)) {
81 MSG_MGR_FATAL("file[%s] error lstat: %s", pFileName, g_strerror(errno));
85 return (int)file_stat.st_size;
89 static void MsgMgrSoundPlayeErrorCallback(int error_code, void *user_data)
91 MSG_MGR_DEBUG("MsgMgrSoundPlayeErrorCallback called [%d]", error_code);
93 MsgMgrSoundPlayStart(NULL, MSG_MGR_SOUND_PLAY_DEFAULT);
96 static void MsgMgrSoundPlayeCompletedCallback(void *user_data)
98 MSG_MGR_DEBUG("MsgMgrSoundPlayeCompletedCallback called");
99 MsgMgrSoundPlayStop();
102 static void MsgMgrSoundPlayeInterruptedCallback(player_interrupted_code_e code, void *user_data)
104 MSG_MGR_DEBUG("MsgMgrSoundPlayeInterruptedCallback called [%d]", code);
105 MsgMgrSoundPlayStop();
108 static void MsgStreamFocusCallback(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state,
109 sound_stream_focus_change_reason_e reason_for_change, int sound_behavior, const char *additional_info, void *user_data)
111 MSG_MGR_DEBUG("MsgStreamFocusCallback called, reason_for_change [%d], additional_info [%s]", reason_for_change, additional_info);
113 if ((focus_mask == SOUND_STREAM_FOCUS_FOR_PLAYBACK) && (focus_state == SOUND_STREAM_FOCUS_STATE_RELEASED)) {
114 MSG_MGR_DEBUG("sound stream focus released");
115 MsgMgrSoundPlayStop();
120 void initMsgMgrSoundPlayer()
123 bFeedbackInit = false;
125 defaultRingtonePath = vconf_get_str(VCONFKEY_SETAPPL_NOTI_RINGTONE_DEFAULT_PATH_STR);
127 if (defaultRingtonePath == NULL || MsgMgrGetFileSize(defaultRingtonePath) < 1) {
128 free(defaultRingtonePath);
129 defaultRingtonePath = NULL;
130 defaultRingtonePath = (char *)DEFAULT_ALERT_FILE;
133 MSG_MGR_DEBUG("defaultRingtonePath [%s]", defaultRingtonePath);
137 void MsgMgrGetRingtonePath(char *userRingtonePath, char **msg_tone_file_path_p)
140 if (vconf_get_int(MSG_SETTING_RINGTONE_TYPE, &tmpVal) != 0) {
141 MSG_MGR_INFO("vcong_get_int() is failed");
143 int ringtoneType = tmpVal;
145 MSG_MGR_DEBUG("Ringtone type = [%d]", ringtoneType);
147 if (ringtoneType == MSG_RINGTONE_TYPE_SILENT) {
148 *msg_tone_file_path_p = NULL;
152 char *tmpFilePath = NULL;
153 *msg_tone_file_path_p = new char[MSG_FILEPATH_LEN_MAX+1];
155 char *msg_tone_file_path = *msg_tone_file_path_p;
157 bool bUserRingtone = userRingtonePath && userRingtonePath[0] != '\0';
159 tmpFilePath = userRingtonePath;
161 if (ringtoneType == MSG_RINGTONE_TYPE_DEFAULT) {
162 tmpFilePath = vconf_get_str(VCONFKEY_SETAPPL_NOTI_MSG_RINGTONE_PATH_STR);
164 tmpFilePath = vconf_get_str(MSG_SETTING_RINGTONE_PATH);
168 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
169 #if 0 /* MSG_DRM_SUPPORT */
170 if ((tmpFilePath == NULL || MsgMgrGetFileSize(tmpFilePath) < 1) || /* wrong ringtone file path */
171 (MsgDrmIsDrmFile(tmpFilePath) && !MsgDrmCheckRingtone(tmpFilePath))) { /* check DRM */
173 if ((tmpFilePath == NULL || MsgMgrGetFileSize(tmpFilePath) < 1)) { /* wrong ringtone file path */
174 if (tmpFilePath && (strcmp(tmpFilePath, "silent") == 0)) {
175 MSG_MGR_DEBUG("Set ringtone to NONE(Silent)");
176 msg_tone_file_path = NULL;
178 MSG_MGR_DEBUG("Set ringtone to defaultRingtonePath.");
179 if (defaultRingtonePath && defaultRingtonePath[0] != '\0') {
180 MSG_MGR_DEBUG("defaultRingtonePath [%s]", defaultRingtonePath);
181 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", defaultRingtonePath);
183 MSG_MGR_DEBUG("defaultRingtonePath is null");
184 msg_tone_file_path = NULL;
188 MSG_MGR_DEBUG("Set ringtone to tmpFilePath.");
189 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", tmpFilePath);
192 if (tmpFilePath && !bUserRingtone) {
198 void MsgMgrGetPlayStatus(bool bVoiceMail, bool *bPlaySound, bool *bPlayVibration, bool *bOnCall)
202 if (!bPlaySound || !bPlayVibration) {
203 MSG_MGR_DEBUG("IN parameter is NULL.");
208 *bPlayVibration = false;
211 int bSoundOn = 0; /* sound setting on notification panel */
212 int bVibrationOn = 0; /* vibration setting on notification panel */
214 if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &bSoundOn) != 0)
215 MSG_MGR_INFO("vconf_get_bool() is failed");
217 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &bVibrationOn) != 0)
218 MSG_MGR_INFO("vconf_get_bool() is failed");
221 #if 0 /* not used value */
222 int bNotiVibrationOn = 0; /* alert vibration */
223 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, &bNotiVibrationOn) != 0)
224 MSG_MGR_INFO("vconf_get_bool() is failed");
227 int bMsgSettingNoti = 1; /* Alert for message notification */
228 int bMsgSettingVibration = 0; /* vibration for message notification */
230 int ringtoneType = MSG_RINGTONE_TYPE_DEFAULT; /*sound type for message notification */
231 bool bMsgSettingSound = true;
233 if (vconf_get_bool(MSG_SETTING_VIBRATION, &bMsgSettingVibration) != 0)
234 MSG_MGR_INFO("vconf_get_bool() is failed");
236 if (vconf_get_bool(MSG_SETTING_NOTIFICATION, &bMsgSettingNoti) != 0)
237 MSG_MGR_INFO("vconf_get_bool() is failed");
240 if (vconf_get_int(MSG_SETTING_RINGTONE_TYPE, &tmpVal) != 0) {
241 MSG_MGR_INFO("vconf_get_int() is failed");
243 ringtoneType = tmpVal;
244 if (ringtoneType == MSG_RINGTONE_TYPE_SILENT)
245 bMsgSettingSound = false;
247 MSG_MGR_SEC_DEBUG("Sound status : Sound mode[%d], Manner mode[%d]", bSoundOn, bVibrationOn);
248 MSG_MGR_SEC_DEBUG("Msg Setting : Noti Alert[%d], vibration[%d], sound[%d], ringtoneType[%d]", bMsgSettingNoti, bMsgSettingVibration, bMsgSettingSound, ringtoneType);
250 cm_call_status_e callStatus = CM_CALL_STATUS_IDLE;
251 /* int alertOnCall = 0; */
253 callStatus = MsgMgrGetCallStatus();
254 MSG_MGR_DEBUG("Call Status [%d]", callStatus);
256 /* Check call status */
257 if (callStatus > CM_CALL_STATUS_IDLE && callStatus < CM_CALL_STATUS_MAX) {
259 *bOnCall = true; /* set call status; */
261 /* 2. Call is not active */
262 MSG_MGR_DEBUG("Call is not active.");
263 recorder_device_state_e recorderState = RECORDER_DEVICE_STATE_IDLE;
264 int ret = recorder_get_device_state(RECORDER_TYPE_AUDIO, &recorderState);
266 MSG_MGR_INFO("recorder_get_device_state() is failed [%d]", ret);
268 if (bVoiceMail) { /* 2-1. Voice message */
269 if (bMsgSettingNoti) {
270 MsgMgrGetPlayStatus(false, bSoundOn, bVibrationOn, bMsgSettingSound, bMsgSettingVibration, bPlaySound, bPlayVibration);
273 MSG_MGR_DEBUG("It doesn't play sound/vibration - voice message.");
275 } else { /* 2-1. Normal message */
276 if (bMsgSettingNoti) {
277 if (recorderState != RECORDER_DEVICE_STATE_RECORDING) {
278 MsgMgrGetPlayStatus(false, bSoundOn, bVibrationOn, bMsgSettingSound, bMsgSettingVibration, bPlaySound, bPlayVibration);
280 MSG_MGR_DEBUG("It doesn't play sound/vibration.");
283 MSG_MGR_DEBUG("It doesn't play sound/vibration.");
292 void MsgMgrGetPlayStatus(bool bOnCall, bool bSound, bool bVibration, bool bMsgSound, bool bMsgVibration, bool *bPlaySound, bool *bPlayVibration)
296 /* samsung basic concept : feedback should follow profile setting.
297 * And if notification setting exist in msg app, then apply it prior to profile when profile either sound or vibration.
298 * But, Play sound when profile is vibration during call, if device does not support haptic */
299 if (bSound || bVibration) {
300 bool bHantic_device = false;
301 #ifdef FEATURE_HAPTIC_ENABLE
302 bHantic_device = true;
304 if (bHantic_device || (bOnCall == false)) {
307 MSG_MGR_DEBUG("Play sound.");
312 MSG_MGR_DEBUG("Play vibration.");
313 *bPlayVibration = true;
317 MSG_MGR_DEBUG("Play vibration.");
318 *bPlayVibration = true;
321 } else { /* during call */
322 if (bMsgSound || bMsgVibration) {
323 MSG_MGR_DEBUG("Play sound.");
333 void MsgMgrSoundPlayStart(const MSG_MGR_ADDRESS_INFO_S *pAddrInfo, MSG_MGR_SOUND_TYPE_T soundType)
337 MSG_MGR_DEBUG("soundType [%d]", soundType);
339 /* check recorder state */
340 recorder_device_state_e recorderState = RECORDER_DEVICE_STATE_IDLE;
341 int ret = recorder_get_device_state(RECORDER_TYPE_VIDEO, &recorderState);
343 MSG_MGR_INFO("recorder_get_device_state() is failed [%d]", ret);
345 MSG_MGR_SEC_DEBUG("Recorder state [%d]", recorderState);
347 if (recorderState == RECORDER_DEVICE_STATE_RECORDING) {
352 MSG_MGR_CONTACT_INFO_S contactInfo = {0, };
354 if (MsgMgrGetContactInfo(pAddrInfo, &contactInfo) != 0) {
355 MSG_MGR_DEBUG("MsgGetContactInfo() fail.");
359 /* get ringtone file path */
360 char *msg_tone_file_path = NULL;
362 if (soundType == MSG_MGR_SOUND_PLAY_EMERGENCY) {
363 msg_tone_file_path = new char[MSG_FILEPATH_LEN_MAX+1];
364 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
365 } else if (soundType == MSG_MGR_SOUND_PLAY_DEFAULT) {
366 msg_tone_file_path = new char[MSG_FILEPATH_LEN_MAX+1];
367 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
368 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", DEFAULT_ALERT_FILE);
370 MsgMgrGetRingtonePath(contactInfo.alerttonePath, &msg_tone_file_path);
372 MSG_MGR_SEC_DEBUG("soundType [%d], Sound File [%s]", soundType, msg_tone_file_path);
374 /* get sound play status */
375 bool bPlaySound = false;
376 bool bPlayVibration = false;
377 bool bVoiceMsg = (soundType == MSG_MGR_SOUND_PLAY_VOICEMAIL)?true:false;
378 bool bOnCall = false;
380 MsgMgrGetPlayStatus(bVoiceMsg, &bPlaySound, &bPlayVibration, &bOnCall);
382 MSG_MGR_SEC_DEBUG("sound=[%d], vibration=[%d], voice_msg?[%d], on_call?[%d]",
383 bPlaySound, bPlayVibration, bVoiceMsg, bOnCall);
387 int err = MsgMgrStreamStart(soundType);
389 if (err != SOUND_MANAGER_ERROR_NONE)
390 MSG_MGR_DEBUG("MsgMgrStreamStart() Failed : %d", err);
392 MsgMgrSoundPlayMelody(msg_tone_file_path);
396 MsgMgrSoundPlayVibration();
398 if (msg_tone_file_path)
399 delete [] msg_tone_file_path;
405 void MsgMgrSoundPlayStop()
410 pthread_mutex_lock(&muMmPlay);
412 if (bPlaying == true && g_PlayerHandle != NULL) {
413 MSG_MGR_DEBUG("stopping the player.");
414 /* Stop playing media contents */
415 err = player_stop(g_PlayerHandle);
417 if (err != PLAYER_ERROR_NONE)
418 MSG_MGR_DEBUG("stopping the player handle failed");
421 if (g_PlayerHandle != NULL) {
422 MSG_MGR_DEBUG("destroy the player.");
424 player_unset_error_cb(g_PlayerHandle);
425 player_unset_completed_cb(g_PlayerHandle);
426 player_unset_interrupted_cb(g_PlayerHandle);
427 player_unprepare(g_PlayerHandle);
428 player_destroy(g_PlayerHandle);
431 g_PlayerHandle = NULL;
434 pthread_mutex_unlock(&muMmPlay);
442 int MsgMgrStreamStart(MSG_MGR_SOUND_TYPE_T soundType)
447 pthread_mutex_lock(&muStream);
449 if (g_stream_info != NULL) {
450 err = sound_manager_destroy_stream_information(g_stream_info);
451 if (err != SOUND_MANAGER_ERROR_NONE)
452 MSG_MGR_DEBUG("sound_manager_destroy_stream_information() Failed : %d", err);
454 g_stream_info = NULL;
457 if (soundType == MSG_MGR_SOUND_PLAY_EMERGENCY)
458 err = sound_manager_create_stream_information(SOUND_STREAM_TYPE_EMERGENCY, MsgStreamFocusCallback, NULL, &g_stream_info);
460 err = sound_manager_create_stream_information(SOUND_STREAM_TYPE_NOTIFICATION, MsgStreamFocusCallback, NULL, &g_stream_info);
462 if (err != SOUND_MANAGER_ERROR_NONE) {
463 MSG_MGR_DEBUG("sound_manager_create_stream_information() Failed : %d", err);
464 pthread_mutex_unlock(&muStream);
468 err = sound_manager_acquire_focus(g_stream_info, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
469 pthread_mutex_unlock(&muStream);
476 void MsgMgrStreamStop()
479 pthread_mutex_lock(&muStream);
481 if (g_stream_info != NULL) {
482 int err = sound_manager_release_focus(g_stream_info, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
483 if (err != SOUND_MANAGER_ERROR_NONE)
484 MSG_MGR_DEBUG("sound_manager_release_focus() Failed : %d", err);
486 err = sound_manager_destroy_stream_information(g_stream_info);
487 if (err != SOUND_MANAGER_ERROR_NONE)
488 MSG_MGR_DEBUG("sound_manager_destroy_stream_information() Failed : %d", err);
490 g_stream_info = NULL;
492 pthread_mutex_unlock(&muStream);
498 void MsgMgrSoundPlayMelody(char *pMsgToneFilePath)
500 int err = PLAYER_ERROR_NONE;
502 if (!pMsgToneFilePath) {
503 MSG_MGR_DEBUG("Ringtone path is NULL");
507 pthread_mutex_lock(&muMmPlay);
509 if (g_stream_info == NULL) {
510 MSG_MGR_DEBUG("g_stream_info is NULL");
511 pthread_mutex_unlock(&muMmPlay);
515 if (g_PlayerHandle) {
516 player_unset_error_cb(g_PlayerHandle);
517 player_unset_completed_cb(g_PlayerHandle);
518 player_unset_interrupted_cb(g_PlayerHandle);
519 player_unprepare(g_PlayerHandle);
520 player_destroy(g_PlayerHandle);
523 err = player_create(&g_PlayerHandle);
525 pthread_mutex_unlock(&muMmPlay);
527 if (err != PLAYER_ERROR_NONE) {
528 MSG_MGR_DEBUG("creating the player handle failed");
532 /* Setting the call back function msg_callback */
533 player_set_error_cb(g_PlayerHandle, MsgMgrSoundPlayeErrorCallback, NULL);
534 player_set_completed_cb(g_PlayerHandle, MsgMgrSoundPlayeCompletedCallback, NULL);
535 player_set_interrupted_cb(g_PlayerHandle, MsgMgrSoundPlayeInterruptedCallback, NULL);
537 player_set_sound_stream_info(g_PlayerHandle, g_stream_info);
540 err = player_set_uri(g_PlayerHandle, (const char *)pMsgToneFilePath);
541 if (err != PLAYER_ERROR_NONE)
542 MSG_MGR_DEBUG("player_set_uri() error : [%d]", err);
544 err = player_prepare(g_PlayerHandle);
545 if (err != PLAYER_ERROR_NONE) {
546 MSG_MGR_DEBUG("player_prepare() error : [%d]", err);
547 if (pMsgToneFilePath != defaultRingtonePath) {
548 pMsgToneFilePath = defaultRingtonePath;
553 } while (err != PLAYER_ERROR_NONE);
556 pthread_mutex_lock(&muMmPlay);
557 MSG_MGR_DEBUG("player_start with [%s]", pMsgToneFilePath);
558 err = player_start(g_PlayerHandle);
560 if (err != PLAYER_ERROR_NONE) {
561 MSG_MGR_DEBUG("player_start, FAIL [%x]", err);
563 /* Add Timer to stop playing after 5 sec. */
565 int g_contact_timer = -1;
566 g_contact_timer = g_timeout_add(MSG_MGR_SOUND_TIMEOUT, (GSourceFunc)MsgSoundMelodyTimeout, NULL);
571 pthread_mutex_unlock(&muMmPlay);
575 void MsgMgrSoundPlayVibration()
581 if (!bFeedbackInit) {
582 int ret = feedback_initialize();
584 if (ret != FEEDBACK_ERROR_NONE) {
585 MSG_MGR_DEBUG("Fail to feedback_initialize : [%d]", ret);
586 bFeedbackInit = false;
589 MSG_MGR_DEBUG("Success to feedback_initialize.");
590 bFeedbackInit = true;
595 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
596 if (ret != FEEDBACK_ERROR_NONE)
597 MSG_MGR_DEBUG("Fail to feedback_play_type");
599 if (vibrationPath && strlen(vibrationPath)) {
600 MSG_MGR_DEBUG("vibrationPath: [%s]", vibrationPath);
601 ret = feedback_set_resource_path(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE, vibrationPath);
602 if (ret != FEEDBACK_ERROR_NONE)
603 MSG_MGR_DEBUG("Fail to feedback_set_resource_path");
604 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
606 if (ret != FEEDBACK_ERROR_NONE)
607 MSG_MGR_DEBUG("Fail to feedback_play_type");
609 ret = feedback_set_resource_path(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE, NULL);
610 if (ret != FEEDBACK_ERROR_NONE)
611 MSG_MGR_DEBUG("Fail to feedback_set_resource_path");
613 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
614 if (ret != FEEDBACK_ERROR_NONE)
615 MSG_MGR_DEBUG("Fail to feedback_play_type");