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 defaultRingtonePath = (char *)DEFAULT_ALERT_FILE;
131 MSG_MGR_DEBUG("defaultRingtonePath [%s]", defaultRingtonePath);
135 void MsgMgrGetRingtonePath(char *userRingtonePath, char **msg_tone_file_path_p)
138 if (vconf_get_int(MSG_SETTING_RINGTONE_TYPE, &tmpVal) != 0) {
139 MSG_MGR_INFO("vcong_get_int() is failed");
141 int ringtoneType = tmpVal;
143 MSG_MGR_DEBUG("Ringtone type = [%d]", ringtoneType);
145 if (ringtoneType == MSG_RINGTONE_TYPE_SILENT) {
146 *msg_tone_file_path_p = NULL;
150 char *tmpFilePath = NULL;
151 *msg_tone_file_path_p = new char[MSG_FILEPATH_LEN_MAX+1];
153 char *msg_tone_file_path = *msg_tone_file_path_p;
155 bool bUserRingtone = userRingtonePath && userRingtonePath[0] != '\0';
157 tmpFilePath = userRingtonePath;
159 if (ringtoneType == MSG_RINGTONE_TYPE_DEFAULT) {
160 tmpFilePath = vconf_get_str(VCONFKEY_SETAPPL_NOTI_MSG_RINGTONE_PATH_STR);
162 tmpFilePath = vconf_get_str(MSG_SETTING_RINGTONE_PATH);
166 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
167 #if 0 /* MSG_DRM_SUPPORT */
168 if ((tmpFilePath == NULL || MsgMgrGetFileSize(tmpFilePath) < 1) || /* wrong ringtone file path */
169 (MsgDrmIsDrmFile(tmpFilePath) && !MsgDrmCheckRingtone(tmpFilePath))) { /* check DRM */
171 if ((tmpFilePath == NULL || MsgMgrGetFileSize(tmpFilePath) < 1)) { /* wrong ringtone file path */
172 if (tmpFilePath && (strcmp(tmpFilePath, "silent") == 0)) {
173 MSG_MGR_DEBUG("Set ringtone to NONE(Silent)");
174 msg_tone_file_path = NULL;
176 MSG_MGR_DEBUG("Set ringtone to defaultRingtonePath.");
177 if (defaultRingtonePath && defaultRingtonePath[0] != '\0') {
178 MSG_MGR_DEBUG("defaultRingtonePath [%s]", defaultRingtonePath);
179 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", defaultRingtonePath);
181 MSG_MGR_DEBUG("defaultRingtonePath is null");
182 msg_tone_file_path = NULL;
186 MSG_MGR_DEBUG("Set ringtone to tmpFilePath.");
187 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", tmpFilePath);
190 if (tmpFilePath && !bUserRingtone) {
196 void MsgMgrGetPlayStatus(bool bVoiceMail, bool *bPlaySound, bool *bPlayVibration, bool *bOnCall)
200 if (!bPlaySound || !bPlayVibration) {
201 MSG_MGR_DEBUG("IN parameter is NULL.");
206 *bPlayVibration = false;
209 int bSoundOn = 0; /* sound setting on notification panel */
210 int bVibrationOn = 0; /* vibration setting on notification panel */
212 if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &bSoundOn) != 0)
213 MSG_MGR_INFO("vconf_get_bool() is failed");
215 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &bVibrationOn) != 0)
216 MSG_MGR_INFO("vconf_get_bool() is failed");
219 #if 0 /* not used value */
220 int bNotiVibrationOn = 0; /* alert vibration */
221 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, &bNotiVibrationOn) != 0)
222 MSG_MGR_INFO("vconf_get_bool() is failed");
225 int bMsgSettingNoti = 1; /* Alert for message notification */
226 int bMsgSettingVibration = 0; /* vibration for message notification */
228 int ringtoneType = MSG_RINGTONE_TYPE_DEFAULT; /*sound type for message notification */
229 bool bMsgSettingSound = true;
231 if (vconf_get_bool(MSG_SETTING_VIBRATION, &bMsgSettingVibration) != 0)
232 MSG_MGR_INFO("vconf_get_bool() is failed");
234 if (vconf_get_bool(MSG_SETTING_NOTIFICATION, &bMsgSettingNoti) != 0)
235 MSG_MGR_INFO("vconf_get_bool() is failed");
238 if (vconf_get_int(MSG_SETTING_RINGTONE_TYPE, &tmpVal) != 0) {
239 MSG_MGR_INFO("vconf_get_int() is failed");
241 ringtoneType = tmpVal;
242 if (ringtoneType == MSG_RINGTONE_TYPE_SILENT)
243 bMsgSettingSound = false;
245 MSG_MGR_SEC_DEBUG("Sound status : Sound mode[%d], Manner mode[%d]", bSoundOn, bVibrationOn);
246 MSG_MGR_SEC_DEBUG("Msg Setting : Noti Alert[%d], vibration[%d], sound[%d], ringtoneType[%d]", bMsgSettingNoti, bMsgSettingVibration, bMsgSettingSound, ringtoneType);
248 cm_call_status_e callStatus = CM_CALL_STATUS_IDLE;
249 /* int alertOnCall = 0; */
251 callStatus = MsgMgrGetCallStatus();
252 MSG_MGR_DEBUG("Call Status [%d]", callStatus);
254 /* Check call status */
255 if (callStatus > CM_CALL_STATUS_IDLE && callStatus < CM_CALL_STATUS_MAX) {
257 *bOnCall = true; /* set call status; */
259 /* 2. Call is not active */
260 MSG_MGR_DEBUG("Call is not active.");
261 recorder_device_state_e recorderState = RECORDER_DEVICE_STATE_IDLE;
262 int ret = recorder_get_device_state(RECORDER_TYPE_AUDIO, &recorderState);
264 MSG_MGR_INFO("recorder_get_device_state() is failed [%d]", ret);
266 if (bVoiceMail) { /* 2-1. Voice message */
267 if (bMsgSettingNoti) {
268 MsgMgrGetPlayStatus(false, bSoundOn, bVibrationOn, bMsgSettingSound, bMsgSettingVibration, bPlaySound, bPlayVibration);
271 MSG_MGR_DEBUG("It doesn't play sound/vibration - voice message.");
273 } else { /* 2-1. Normal message */
274 if (bMsgSettingNoti) {
275 if (recorderState != RECORDER_DEVICE_STATE_RECORDING) {
276 MsgMgrGetPlayStatus(false, bSoundOn, bVibrationOn, bMsgSettingSound, bMsgSettingVibration, bPlaySound, bPlayVibration);
278 MSG_MGR_DEBUG("It doesn't play sound/vibration.");
281 MSG_MGR_DEBUG("It doesn't play sound/vibration.");
290 void MsgMgrGetPlayStatus(bool bOnCall, bool bSound, bool bVibration, bool bMsgSound, bool bMsgVibration, bool *bPlaySound, bool *bPlayVibration)
294 /* samsung basic concept : feedback should follow profile setting.
295 * And if notification setting exist in msg app, then apply it prior to profile when profile either sound or vibration.
296 * But, Play sound when profile is vibration during call, if device does not support haptic */
297 if (bSound || bVibration) {
298 bool bHantic_device = false;
299 #ifdef FEATURE_HAPTIC_ENABLE
300 bHantic_device = true;
302 if (bHantic_device || (bOnCall == false)) {
305 MSG_MGR_DEBUG("Play sound.");
310 MSG_MGR_DEBUG("Play vibration.");
311 *bPlayVibration = true;
315 MSG_MGR_DEBUG("Play vibration.");
316 *bPlayVibration = true;
319 } else { /* during call */
320 if (bMsgSound || bMsgVibration) {
321 MSG_MGR_DEBUG("Play sound.");
331 void MsgMgrSoundPlayStart(const MSG_MGR_ADDRESS_INFO_S *pAddrInfo, MSG_MGR_SOUND_TYPE_T soundType)
335 MSG_MGR_DEBUG("soundType [%d]", soundType);
337 /* check recorder state */
338 recorder_device_state_e recorderState = RECORDER_DEVICE_STATE_IDLE;
339 int ret = recorder_get_device_state(RECORDER_TYPE_VIDEO, &recorderState);
341 MSG_MGR_INFO("recorder_get_device_state() is failed [%d]", ret);
343 MSG_MGR_SEC_DEBUG("Recorder state [%d]", recorderState);
345 if (recorderState == RECORDER_DEVICE_STATE_RECORDING) {
350 MSG_MGR_CONTACT_INFO_S contactInfo = {0, };
352 if (MsgMgrGetContactInfo(pAddrInfo, &contactInfo) != 0) {
353 MSG_MGR_DEBUG("MsgGetContactInfo() fail.");
357 /* get ringtone file path */
358 char *msg_tone_file_path = NULL;
360 if (soundType == MSG_MGR_SOUND_PLAY_EMERGENCY) {
361 msg_tone_file_path = new char[MSG_FILEPATH_LEN_MAX+1];
362 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
363 } else if (soundType == MSG_MGR_SOUND_PLAY_DEFAULT) {
364 msg_tone_file_path = new char[MSG_FILEPATH_LEN_MAX+1];
365 memset(msg_tone_file_path, 0x00, sizeof(char)*(MSG_FILEPATH_LEN_MAX+1));
366 snprintf(msg_tone_file_path, MSG_FILEPATH_LEN_MAX, "%s", DEFAULT_ALERT_FILE);
368 MsgMgrGetRingtonePath(contactInfo.alerttonePath, &msg_tone_file_path);
370 MSG_MGR_SEC_DEBUG("soundType [%d], Sound File [%s]", soundType, msg_tone_file_path);
372 /* get sound play status */
373 bool bPlaySound = false;
374 bool bPlayVibration = false;
375 bool bVoiceMsg = (soundType == MSG_MGR_SOUND_PLAY_VOICEMAIL)?true:false;
376 bool bOnCall = false;
378 MsgMgrGetPlayStatus(bVoiceMsg, &bPlaySound, &bPlayVibration, &bOnCall);
380 MSG_MGR_SEC_DEBUG("sound=[%d], vibration=[%d], voice_msg?[%d], on_call?[%d]",
381 bPlaySound, bPlayVibration, bVoiceMsg, bOnCall);
385 int err = MsgMgrStreamStart(soundType);
387 if (err != SOUND_MANAGER_ERROR_NONE)
388 MSG_MGR_DEBUG("MsgMgrStreamStart() Failed : %d", err);
390 MsgMgrSoundPlayMelody(msg_tone_file_path);
394 MsgMgrSoundPlayVibration();
396 if (msg_tone_file_path)
397 delete [] msg_tone_file_path;
403 void MsgMgrSoundPlayStop()
408 pthread_mutex_lock(&muMmPlay);
410 if (bPlaying == true && g_PlayerHandle != NULL) {
411 MSG_MGR_DEBUG("stopping the player.");
412 /* Stop playing media contents */
413 err = player_stop(g_PlayerHandle);
415 if (err != PLAYER_ERROR_NONE)
416 MSG_MGR_DEBUG("stopping the player handle failed");
419 if (g_PlayerHandle != NULL) {
420 MSG_MGR_DEBUG("destroy the player.");
422 player_unset_error_cb(g_PlayerHandle);
423 player_unset_completed_cb(g_PlayerHandle);
424 player_unset_interrupted_cb(g_PlayerHandle);
425 player_unprepare(g_PlayerHandle);
426 player_destroy(g_PlayerHandle);
429 g_PlayerHandle = NULL;
432 pthread_mutex_unlock(&muMmPlay);
440 int MsgMgrStreamStart(MSG_MGR_SOUND_TYPE_T soundType)
445 pthread_mutex_lock(&muStream);
447 if (g_stream_info != NULL) {
448 err = sound_manager_destroy_stream_information(g_stream_info);
449 if (err != SOUND_MANAGER_ERROR_NONE)
450 MSG_MGR_DEBUG("sound_manager_destroy_stream_information() Failed : %d", err);
452 g_stream_info = NULL;
455 if (soundType == MSG_MGR_SOUND_PLAY_EMERGENCY)
456 err = sound_manager_create_stream_information(SOUND_STREAM_TYPE_EMERGENCY, MsgStreamFocusCallback, NULL, &g_stream_info);
458 err = sound_manager_create_stream_information(SOUND_STREAM_TYPE_NOTIFICATION, MsgStreamFocusCallback, NULL, &g_stream_info);
460 if (err != SOUND_MANAGER_ERROR_NONE) {
461 MSG_MGR_DEBUG("sound_manager_create_stream_information() Failed : %d", err);
462 pthread_mutex_unlock(&muStream);
466 err = sound_manager_acquire_focus(g_stream_info, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
467 pthread_mutex_unlock(&muStream);
474 void MsgMgrStreamStop()
477 pthread_mutex_lock(&muStream);
479 if (g_stream_info != NULL) {
480 int err = sound_manager_release_focus(g_stream_info, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL);
481 if (err != SOUND_MANAGER_ERROR_NONE)
482 MSG_MGR_DEBUG("sound_manager_release_focus() Failed : %d", err);
484 err = sound_manager_destroy_stream_information(g_stream_info);
485 if (err != SOUND_MANAGER_ERROR_NONE)
486 MSG_MGR_DEBUG("sound_manager_destroy_stream_information() Failed : %d", err);
488 g_stream_info = NULL;
490 pthread_mutex_unlock(&muStream);
496 void MsgMgrSoundPlayMelody(char *pMsgToneFilePath)
498 int err = PLAYER_ERROR_NONE;
500 if (!pMsgToneFilePath) {
501 MSG_MGR_DEBUG("Ringtone path is NULL");
505 pthread_mutex_lock(&muMmPlay);
507 if (g_stream_info == NULL) {
508 MSG_MGR_DEBUG("g_stream_info is NULL");
509 pthread_mutex_unlock(&muMmPlay);
513 if (g_PlayerHandle) {
514 player_unset_error_cb(g_PlayerHandle);
515 player_unset_completed_cb(g_PlayerHandle);
516 player_unset_interrupted_cb(g_PlayerHandle);
517 player_unprepare(g_PlayerHandle);
518 player_destroy(g_PlayerHandle);
521 err = player_create(&g_PlayerHandle);
523 pthread_mutex_unlock(&muMmPlay);
525 if (err != PLAYER_ERROR_NONE) {
526 MSG_MGR_DEBUG("creating the player handle failed");
530 /* Setting the call back function msg_callback */
531 player_set_error_cb(g_PlayerHandle, MsgMgrSoundPlayeErrorCallback, NULL);
532 player_set_completed_cb(g_PlayerHandle, MsgMgrSoundPlayeCompletedCallback, NULL);
533 player_set_interrupted_cb(g_PlayerHandle, MsgMgrSoundPlayeInterruptedCallback, NULL);
535 player_set_audio_policy_info(g_PlayerHandle, g_stream_info);
538 err = player_set_uri(g_PlayerHandle, (const char *)pMsgToneFilePath);
539 if (err != PLAYER_ERROR_NONE)
540 MSG_MGR_DEBUG("player_set_uri() error : [%d]", err);
542 err = player_prepare(g_PlayerHandle);
543 if (err != PLAYER_ERROR_NONE) {
544 MSG_MGR_DEBUG("player_prepare() error : [%d]", err);
545 if (pMsgToneFilePath != defaultRingtonePath) {
546 pMsgToneFilePath = defaultRingtonePath;
551 } while (err != PLAYER_ERROR_NONE);
554 pthread_mutex_lock(&muMmPlay);
555 MSG_MGR_DEBUG("player_start with [%s]", pMsgToneFilePath);
556 err = player_start(g_PlayerHandle);
558 if (err != PLAYER_ERROR_NONE) {
559 MSG_MGR_DEBUG("player_start, FAIL [%x]", err);
561 /* Add Timer to stop playing after 5 sec. */
563 int g_contact_timer = -1;
564 g_contact_timer = g_timeout_add(MSG_MGR_SOUND_TIMEOUT, (GSourceFunc)MsgSoundMelodyTimeout, NULL);
569 pthread_mutex_unlock(&muMmPlay);
573 void MsgMgrSoundPlayVibration()
579 if (!bFeedbackInit) {
580 int ret = feedback_initialize();
582 if (ret != FEEDBACK_ERROR_NONE) {
583 MSG_MGR_DEBUG("Fail to feedback_initialize : [%d]", ret);
584 bFeedbackInit = false;
587 MSG_MGR_DEBUG("Success to feedback_initialize.");
588 bFeedbackInit = true;
593 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
594 if (ret != FEEDBACK_ERROR_NONE)
595 MSG_MGR_DEBUG("Fail to feedback_play_type");
597 if (vibrationPath && strlen(vibrationPath)) {
598 MSG_MGR_DEBUG("vibrationPath: [%s]", vibrationPath);
599 ret = feedback_set_resource_path(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE, vibrationPath);
600 if (ret != FEEDBACK_ERROR_NONE)
601 MSG_MGR_DEBUG("Fail to feedback_set_resource_path");
602 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
604 if (ret != FEEDBACK_ERROR_NONE)
605 MSG_MGR_DEBUG("Fail to feedback_play_type");
607 ret = feedback_set_resource_path(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE, NULL);
608 if (ret != FEEDBACK_ERROR_NONE)
609 MSG_MGR_DEBUG("Fail to feedback_set_resource_path");
611 ret = feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_MESSAGE);
612 if (ret != FEEDBACK_ERROR_NONE)
613 MSG_MGR_DEBUG("Fail to feedback_play_type");