08905ab620f1a1f79fc9f2280454377f76ce4c96
[platform/core/system/libsvi.git] / src / sound.c
1 /*
2  * libfeedback
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <limits.h>
28 #include <vconf.h>
29 #include <mm_sound_private.h>
30
31 #include <feedback-ids.h>
32 #include "profiles.h"
33 #include "devices.h"
34 #include "log.h"
35 #include "parser.h"
36
37 #define SOUND_CONF_FILE FEEDBACK_SYS_RO_SHARE"/feedback/sound.conf"
38
39 /* Temporary keys */
40 #ifndef VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL
41 #define VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL "db/setting/sound/button_sounds"
42 #endif
43
44 static int sndstatus;
45 static int touch_sndstatus;
46 static int keytone_sndstatus;
47 static struct feedback_config_info sound_info = {
48         .name = "Sound",
49 };
50
51 static char *get_data(feedback_pattern_e pattern)
52 {
53         char *data;
54         int i;
55         int index = -1;
56
57         if (pattern <= FEEDBACK_PATTERN_NONE ||
58             pattern >= profile->max_pattern)
59                 return NULL;
60
61         for (i = 0; i < profile->get_num_of_pattern(); i++) {
62                 if (pattern == sound_info.data[i].pattern) {
63                         index = i;
64                         break;
65                 }
66         }
67         if (index < 0) {
68                 _E("Not supported pattern : %d", pattern);
69                 return NULL;
70         }
71
72         if (sound_info.data[index].changed)
73                 data = sound_info.data[index].changed;
74         else
75                 data = sound_info.data[index].origin;
76
77         return data;
78 }
79
80 inline int is_sound_mode(void)
81 {
82         return sndstatus;
83 }
84
85 inline int is_touch_sndstatus(void)
86 {
87         return touch_sndstatus;
88 }
89
90 inline int is_keytone_sndstatus(void)
91 {
92         return keytone_sndstatus;
93 }
94
95 //LCOV_EXCL_START Not called Callback
96 static void feedback_touch_sndstatus_cb(keynode_t *key, void* data)
97 {
98         touch_sndstatus = vconf_keynode_get_bool(key);
99 }
100
101 static void feedback_keytone_sndstatus_cb(keynode_t *key, void* data)
102 {
103         keytone_sndstatus = vconf_keynode_get_bool(key);
104 }
105 //LCOV_EXCL_STOP
106
107 static void sound_init(void)
108 {
109         int ret;
110
111         /* get sound data */
112         feedback_load_config(SOUND_CONF_FILE, &sound_info);
113
114         /* check sound status */
115         if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0)
116                 _W("VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL ==> FAIL!!"); //LCOV_EXCL_LINE
117
118         if (vconf_get_bool(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, &keytone_sndstatus) < 0)
119                 _W("VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL ==> FAIL!!"); //LCOV_EXCL_LINE
120
121         if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) {
122                 _D("fail to get sound status, will work as turning off"); //LCOV_EXCL_LINE
123                 sndstatus = 0;
124         }
125
126         /* add watch for status value */
127         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb, NULL);
128         if (ret != 0)
129                 _W("Add watch for VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL failed");
130         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, feedback_keytone_sndstatus_cb, NULL);
131         if (ret != 0)
132                 _W("Add watch for VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL failed");
133 }
134
135 static void sound_exit(void)
136 {
137         int ret;
138
139         /* remove watch */
140         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb);
141         if (ret != 0)
142                 _W("Remove watch for VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL failed");
143         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, feedback_keytone_sndstatus_cb);
144         if (ret != 0)
145                 _W("Remove watch for VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL failed");
146
147         /* free sound data */
148         feedback_free_config(&sound_info);
149 }
150
151 static int sound_play(feedback_pattern_e pattern)
152 {
153         struct stat buf;
154         int retry = FEEDBACK_RETRY_CNT, ret;
155         char *path;
156         int level;
157
158         if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) {
159                 _D("fail to get sound status, will work as turning off"); //LCOV_EXCL_LINE
160                 sndstatus = 0;
161         }
162
163         if (sndstatus == 0 && profile->get_always_alert_case &&
164             !profile->get_always_alert_case(FEEDBACK_TYPE_SOUND, pattern)) {
165                 _D("Sound condition is OFF (sndstatus : %d)", sndstatus); //LCOV_EXCL_LINE
166                 return 0;
167         }
168
169         if (sndstatus && profile->get_always_off_case &&
170             profile->get_always_off_case(FEEDBACK_TYPE_SOUND, pattern)) {
171                 _D("Sound always off condition(pattern %s)", profile->str_pattern(pattern)); //LCOV_EXCL_LINE
172                 return 0;
173         }
174
175         /* get sound file path */
176         path = get_data(pattern);
177         if (!path || stat(path, &buf)) {
178                 _E("Not supported sound pattern(pattern %d)", pattern); //LCOV_EXCL_LINE
179                 return -ENOTSUP;
180         }
181
182         /* play sound file */
183         do {
184                 if (profile->get_strength_type)
185                         level = profile->get_strength_type(FEEDBACK_TYPE_SOUND, pattern);
186                 else
187                         level = VOLUME_TYPE_SYSTEM;
188
189                 ret = mm_sound_play_keysound(path, level);
190                 if (ret == MM_ERROR_NONE) {
191                         _D("Play success! SND filename is %s", path);
192                         return 0;
193                 }
194                 _E("mm_sound_play_keysound() returned error(%d)", ret); //LCOV_EXCL_LINE
195         } while (retry--);
196
197         return -EPERM;
198 }
199
200 static int sound_is_supported(feedback_pattern_e pattern, bool *supported)
201 {
202         struct stat buf;
203         char *path;
204         bool ret = true;
205
206         if (!supported) {
207                 _E("Invalid parameter : supported(NULL)"); //LCOV_EXCL_LINE
208                 return -EINVAL;
209         }
210
211         /* get sound file path */
212         path = get_data(pattern);
213         if (!path || stat(path, &buf)) {
214                 _D("%d is not presents", pattern);
215                 ret = false;
216         }
217
218         *supported = ret;
219         return 0;
220 }
221
222 //LCOV_EXCL_START Not used function
223 static int sound_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
224 {
225         char *cur_path;
226         int ret = 0;
227
228         if (!buf || buflen <= 0)
229                 return -EINVAL;
230
231         /* get sound file path */
232         cur_path = get_data(pattern);
233         if (!cur_path) {
234                 _E("This pattern(%s) in sound type is not supported to play",
235                                 profile->str_pattern(pattern));
236                 cur_path = "NULL";
237                 ret = -ENOENT;
238         }
239
240         snprintf(buf, buflen, "%s", cur_path);
241         return ret;
242 }
243 //LCOV_EXCL_STOP
244
245 //LCOV_EXCL_START Not used function
246 static int sound_set_path(feedback_pattern_e pattern, char *path)
247 {
248         struct stat buf;
249         int i;
250         int index = -1;
251
252         /*
253          * check the path is valid
254          * if path is null, below operation is ignored
255          */
256         if (path && stat(path, &buf)) {
257                 _E("%s is not presents", path);
258                 return -errno;
259         }
260
261         if (!profile->str_pattern(pattern)) {
262                 _E("%d is not supported", pattern);
263                 return -EPERM;
264         }
265
266         for (i = 0; i < profile->get_num_of_pattern(); i++) {
267                 if (pattern == sound_info.data[i].pattern) {
268                         index = i;
269                         break;
270                 }
271         }
272
273         if (index < 0) {
274                 for (i = 0; i < profile->get_num_of_pattern(); i++) {
275                         if (sound_info.data[i].pattern != -1)
276                                 continue;
277
278                         sound_info.data[i].pattern = pattern;
279                         sound_info.data[i].changed = strdup(path);
280                         _D("The file of pattern(%s) is changed to [%s]",
281                                         profile->str_pattern(pattern), path);
282
283                         return 0;
284                 }
285                 _E("%d is not supported", pattern);
286                 return -EPERM;
287         }
288
289         if (sound_info.data[index].changed) {
290                 free(sound_info.data[index].changed);
291                 sound_info.data[index].changed = NULL;
292         }
293
294         /* if path is NULL, this pattern set to default file */
295         if (path)
296                 sound_info.data[index].changed = strdup(path);
297
298         _D("The file of pattern(%s) is changed to [%s]",
299                         profile->str_pattern(pattern), path);
300         return 0;
301 }
302 //LCOV_EXCL_STOP
303
304 static const struct device_ops sound_device_ops = {
305         .type = FEEDBACK_TYPE_SOUND,
306         .name = "Sound",
307         .init = sound_init,
308         .exit = sound_exit,
309         .play = sound_play,
310         .is_supported = sound_is_supported,
311         .get_path = sound_get_path,
312         .set_path = sound_set_path,
313 };
314
315 DEVICE_OPS_REGISTER(&sound_device_ops);