3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
28 #include <mm_sound_private.h>
31 #include "feedback-internal.h"
32 #include "feedback-str.h"
33 #include "feedback-log.h"
36 #define FEEDBACK_SOUND_DIR FEEDBACK_DATA_DIR"/sound"
37 #define FEEDBACK_SOUND_TOUCH_DIR FEEDBACK_SOUND_DIR"/touch"
38 #define FEEDBACK_SOUND_OPER_DIR FEEDBACK_SOUND_DIR"/operation"
40 static const char* sound_file[] = {
41 /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : GENERAL */
42 FEEDBACK_SOUND_TOUCH_DIR"/touch.wav",
43 /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : TEXT_NUMERIC_INPUT */
44 FEEDBACK_SOUND_TOUCH_DIR"/sip.wav",
45 FEEDBACK_SOUND_TOUCH_DIR"/sip_backspace.wav",
46 FEEDBACK_SOUND_TOUCH_DIR"/sip.wav",
47 /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : DAILER */
48 FEEDBACK_SOUND_TOUCH_DIR"/key0.wav",
49 FEEDBACK_SOUND_TOUCH_DIR"/key1.wav",
50 FEEDBACK_SOUND_TOUCH_DIR"/key2.wav",
51 FEEDBACK_SOUND_TOUCH_DIR"/key3.wav",
52 FEEDBACK_SOUND_TOUCH_DIR"/key4.wav",
53 FEEDBACK_SOUND_TOUCH_DIR"/key5.wav",
54 FEEDBACK_SOUND_TOUCH_DIR"/key6.wav",
55 FEEDBACK_SOUND_TOUCH_DIR"/key7.wav",
56 FEEDBACK_SOUND_TOUCH_DIR"/key8.wav",
57 FEEDBACK_SOUND_TOUCH_DIR"/key9.wav",
58 FEEDBACK_SOUND_TOUCH_DIR"/keyasterisk.wav",
59 FEEDBACK_SOUND_TOUCH_DIR"/keysharp.wav",
60 /* TOUCH : H/W OR SOFT TOUCH : HOLD(TAP & HOLD) */
62 /* TOUCH : H/W OR SOFT TOUCH : MULTI TAP */
64 /* TOUCH : H/W OR SOFT TOUCH : TAP */
66 /* TOUCH : H/W OR SOFT TOUCH : TAP & HOLD */
69 /* NOTIFICATION : INCOMING : MESSAGE */
71 /* NOTIFICATION : INCOMING : MESSAGE ALERT ON CALL */
73 /* NOTIFICATION : INCOMING : EMAIL */
75 /* NOTIFICATION : INCOMING : EMAIL ALERT ON CALL */
77 /* NOTIFICATION : ALARM : WAKEUP */
79 /* NOTIFICATION : ALARM : WAKEUP ALERT ON CALL */
81 /* NOTIFICATION : ALARM : SCHEDULE */
83 /* NOTIFICATION : ALARM : SCHEDULE ALERT ON CALL */
85 /* NOTIFICATION : ALARM : TIMER */
87 /* NOTIFICATION : ALARM : TIMER ALERT ON CALL */
89 /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) */
90 FEEDBACK_SOUND_OPER_DIR"/call_connect.wav",
91 /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) ALERT ON CALL */
92 FEEDBACK_SOUND_OPER_DIR"/call_connect.wav",
94 /* OPERATION : POWER ON/OFF */
95 FEEDBACK_SOUND_OPER_DIR"/power_on.wav",
97 /* OPERATION : CHARGECONN */
98 FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav",
99 /* OPERATION : CHARGECONN ALERT ON CALL */
100 FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav",
101 /* OPERATION : FULLCHAREGED */
102 FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav",
103 /* OPERATION : FULLCHAREGED ALERT ON CALL */
104 FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav",
105 /* OPERATION : LOW BATTERY */
106 FEEDBACK_SOUND_OPER_DIR"/low_battery.wav",
107 /* OPERATION : LOW BATTERY ALERT ON CALL */
108 FEEDBACK_SOUND_OPER_DIR"/low_battery.wav",
109 /* OPERATION : LOCK/UNLOCK */
110 FEEDBACK_SOUND_OPER_DIR"/lock.wav",
111 FEEDBACK_SOUND_OPER_DIR"/unlock.wav",
112 /* OPERATION : CALL CONNECT/ DISCONNECT */
113 FEEDBACK_SOUND_OPER_DIR"/call_connect.wav",
114 FEEDBACK_SOUND_OPER_DIR"/call_disconnect.wav",
115 /* OPERATION : MINUTE MINDER */
116 FEEDBACK_SOUND_OPER_DIR"/minute_minder.wav",
117 /* OPERATION : VIBRATION */
119 /* OPERATION : CAMERA SHUTTER / SCREEN CAPTURE */
120 FEEDBACK_SOUND_OPER_DIR"/shutter.wav",
121 /* OPERATION : LIST RE-ORDER */
122 FEEDBACK_SOUND_OPER_DIR"/list_reorder.wav",
123 /* OPERATION : LIST SLIDER */
124 FEEDBACK_SOUND_OPER_DIR"/slider_sweep.wav",
125 /* OPERATION : VOLUME KEY */
126 FEEDBACK_SOUND_OPER_DIR"/volume_control.wav",
129 static int sndstatus;
130 static int touch_sndstatus;
133 static void feedback_sndstatus_cb(keynode_t *key, void* data)
135 sndstatus = vconf_keynode_get_bool(key);
138 static void feedback_touch_sndstatus_cb(keynode_t *key, void* data)
140 touch_sndstatus = vconf_keynode_get_bool(key);
143 static void feedback_soundon_cb(keynode_t *key, void* data)
145 soundon = vconf_keynode_get_int(key);
148 static volume_type_t get_volume_type(feedback_pattern_e pattern)
150 if (pattern == FEEDBACK_PATTERN_TAP)
151 return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_TOUCH;
152 else if (pattern >= FEEDBACK_PATTERN_KEY0 && pattern <= FEEDBACK_PATTERN_KEY_SHARP)
153 return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_DIALER;
154 else if (pattern == FEEDBACK_PATTERN_VOLUME_KEY)
155 return VOLUME_TYPE_RINGTONE;
157 return VOLUME_TYPE_SYSTEM;
160 static bool get_always_alert_case(feedback_pattern_e pattern)
163 case FEEDBACK_PATTERN_WAKEUP:
164 case FEEDBACK_PATTERN_WAKEUP_ON_CALL:
172 static int change_symlink(const char *sym_path, const char *new_path)
176 assert(sym_path != NULL && strlen(sym_path));
177 assert(new_path != NULL && strlen(new_path));
179 /* check symbolic link file existence */
180 if (stat(sym_path, &buf)) {
181 FEEDBACK_ERROR("file(%s) is not presents", sym_path);
185 if (unlink(sym_path) < 0)
186 FEEDBACK_LOG("unlink(%s) : %s", sym_path, strerror(errno));
188 if (symlink(new_path, sym_path) < 0) {
189 FEEDBACK_ERROR("symlink(%s) : %s", sym_path, strerror(errno));
196 static int restore_default_file(feedback_pattern_e pattern)
198 char default_path[PATH_MAX] = {0,};
199 const char *cur_path;
203 cur_path = sound_file[pattern];
204 /* if there isn't cur_path, it already returns before calling this api */
205 if (cur_path == NULL || strlen(cur_path) == 0) {
206 FEEDBACK_ERROR("Invalid parameter : cur_path(NULL)");
210 temp = strcat(default_path, FEEDBACK_ORIGIN_DATA_DIR);
211 strcat(temp, cur_path+strlen(FEEDBACK_DATA_DIR));
212 FEEDBACK_LOG("default_path : %s", default_path);
214 ret = change_symlink(cur_path, default_path);
216 FEEDBACK_ERROR("change_symlink is failed");
223 static void sound_init(void)
226 if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0)
227 FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) ==> FAIL!!");
229 if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0)
230 FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) ==> FAIL!!");
232 if (vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) < 0)
233 FEEDBACK_ERROR("vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) ==> FAIL!!");
235 /* add watch for status value */
236 vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb, NULL);
237 vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb, NULL);
238 vconf_notify_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb, NULL);
241 static void sound_exit(void)
244 vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb);
245 vconf_ignore_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb);
246 vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb);
249 static int sound_play(feedback_pattern_e pattern)
252 int retry = FEEDBACK_RETRY_CNT, ret;
254 if (sndstatus == 0 && !get_always_alert_case(pattern)) {
255 FEEDBACK_LOG("Sound condition is OFF (sndstatus : %d)", sndstatus);
259 if (soundon == 1 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) {
260 FEEDBACK_LOG("Touch feedback sound doesn't work during playing sound");
264 if (touch_sndstatus == 0 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) {
265 FEEDBACK_LOG("Touch Sound condition is OFF and pattern is touch type (touch_sndstatus : %d, pattern : %s)", touch_sndstatus, str_pattern[pattern]);
269 if (callstatus != VCONFKEY_CALL_OFF) {
270 pattern = feedback_get_alert_on_call_key(pattern);
271 FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]);
274 if (sound_file[pattern] == NULL) {
275 FEEDBACK_LOG("This case(%s) does not play sound", str_pattern[pattern]);
279 if (stat(sound_file[pattern], &buf)) {
280 FEEDBACK_ERROR("%s is not presents", sound_file[pattern]);
281 ret = restore_default_file(pattern);
283 FEEDBACK_ERROR("restore_default_file(%s) error", str_pattern[pattern]);
286 FEEDBACK_LOG("%s is restored", sound_file[pattern]);
290 ret = mm_sound_play_keysound(sound_file[pattern], get_volume_type(pattern));
291 if (ret == MM_ERROR_NONE) {
292 FEEDBACK_LOG("Play success! SND filename is %s", sound_file[pattern]);
295 FEEDBACK_ERROR("mm_sound_play_keysound() returned error(%d)", ret);
301 static int sound_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
303 const char *cur_path;
304 int retry = FEEDBACK_RETRY_CNT;
306 assert(buf != NULL && buflen > 0);
308 cur_path = sound_file[pattern];
309 if (cur_path == NULL) {
310 FEEDBACK_ERROR("This pattern(%s) in sound type is not supported to play", str_pattern[pattern]);
311 snprintf(buf, buflen, "NULL");
316 if(readlink(cur_path, buf, buflen) < 0) {
317 FEEDBACK_ERROR("readlink is failed : %s", strerror(errno));
325 static int sound_set_path(feedback_pattern_e pattern, char *path)
327 const char *cur_path;
330 assert(path != NULL);
332 if (access(path, F_OK) != 0) {
333 FEEDBACK_ERROR("Invalid parameter : path does not exist");
337 cur_path = sound_file[pattern];
338 if (cur_path == NULL) {
339 FEEDBACK_ERROR("This pattern(%s) in sound type is not supported to play", str_pattern[pattern]);
343 ret = change_symlink(cur_path, path);
345 FEEDBACK_ERROR("change_symlink is failed");
352 static const struct device_ops sound_device_ops = {
353 .type = FEEDBACK_TYPE_SOUND,
357 .get_path = sound_get_path,
358 .set_path = sound_set_path,
361 DEVICE_OPS_REGISTER(&sound_device_ops);