Remove build dependencies on profile
[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
55         if (pattern <= FEEDBACK_PATTERN_NONE ||
56             pattern >= profile->max_pattern)
57                 return NULL;
58
59         if (sound_info.data[pattern].changed)
60                 data = sound_info.data[pattern].changed;
61         else
62                 data = sound_info.data[pattern].origin;
63
64         return data;
65 }
66
67 inline int is_sound_mode(void)
68 {
69         return sndstatus;
70 }
71
72 inline int is_touch_sndstatus(void)
73 {
74         return touch_sndstatus;
75 }
76
77 inline int is_keytone_sndstatus(void)
78 {
79         return keytone_sndstatus;
80 }
81
82 //LCOV_EXCL_START Not called Callback
83 static void feedback_touch_sndstatus_cb(keynode_t *key, void* data)
84 {
85         touch_sndstatus = vconf_keynode_get_bool(key);
86 }
87
88 static void feedback_keytone_sndstatus_cb(keynode_t *key, void* data)
89 {
90         keytone_sndstatus = vconf_keynode_get_bool(key);
91 }
92 //LCOV_EXCL_STOP
93
94 static void sound_init(void)
95 {
96         /* get sound data */
97         feedback_load_config(SOUND_CONF_FILE, &sound_info);
98
99         /* check sound status */
100         if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0)
101                 _W("VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL ==> FAIL!!"); //LCOV_EXCL_LINE
102
103         if (vconf_get_bool(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, &keytone_sndstatus) < 0)
104                 _W("VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL ==> FAIL!!"); //LCOV_EXCL_LINE
105
106         if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) {
107                 _D("fail to get sound status, will work as turning off"); //LCOV_EXCL_LINE
108                 sndstatus = 0;
109         }
110
111         /* add watch for status value */
112         vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb, NULL);
113         vconf_notify_key_changed(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, feedback_keytone_sndstatus_cb, NULL);
114 }
115
116 static void sound_exit(void)
117 {
118         /* remove watch */
119         vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb);
120         vconf_ignore_key_changed(VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL, feedback_keytone_sndstatus_cb);
121
122         /* free sound data */
123         feedback_free_config(&sound_info);
124 }
125
126 static int sound_play(feedback_pattern_e pattern)
127 {
128         struct stat buf;
129         int retry = FEEDBACK_RETRY_CNT, ret;
130         char *path;
131         int level;
132
133         if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) {
134                 _D("fail to get sound status, will work as turning off"); //LCOV_EXCL_LINE
135                 sndstatus = 0;
136         }
137
138         if (sndstatus == 0 && profile->get_always_alert_case &&
139             !profile->get_always_alert_case(FEEDBACK_TYPE_SOUND, pattern)) {
140                 _D("Sound condition is OFF (sndstatus : %d)", sndstatus); //LCOV_EXCL_LINE
141                 return 0;
142         }
143
144         if (sndstatus && profile->get_always_off_case &&
145             profile->get_always_off_case(FEEDBACK_TYPE_SOUND, pattern)) {
146                 _D("Sound always off condition(pattern %s)", profile->str_pattern(pattern)); //LCOV_EXCL_LINE
147                 return 0;
148         }
149
150         /* get sound file path */
151         path = get_data(pattern);
152         if (!path || stat(path, &buf)) {
153                 _E("Not supported sound pattern(path %s pattern %d)", path, pattern); //LCOV_EXCL_LINE
154                 return -ENOTSUP;
155         }
156
157         /* play sound file */
158         do {
159                 if (profile->get_strength_type)
160                         level = profile->get_strength_type(FEEDBACK_TYPE_SOUND, pattern);
161                 else
162                         level = VOLUME_TYPE_SYSTEM;
163
164                 ret = mm_sound_play_keysound(path, level);
165                 if (ret == MM_ERROR_NONE) {
166                         _D("Play success! SND filename is %s", path);
167                         return 0;
168                 }
169                 _E("mm_sound_play_keysound() returned error(%d)", ret); //LCOV_EXCL_LINE
170         } while (retry--);
171
172         return -EPERM;
173 }
174
175 static int sound_is_supported(feedback_pattern_e pattern, bool *supported)
176 {
177         struct stat buf;
178         char *path;
179         bool ret = true;
180
181         if (!supported) {
182                 _E("Invalid parameter : supported(NULL)"); //LCOV_EXCL_LINE
183                 return -EINVAL;
184         }
185
186         /* get sound file path */
187         path = get_data(pattern);
188         if (!path || stat(path, &buf)) {
189                 _E("%s is not presents", path);
190                 ret = false;
191         }
192
193         *supported = ret;
194         return 0;
195 }
196
197 static int sound_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
198 {
199         char *cur_path;
200         int ret = 0;
201
202         if (!buf || buflen <= 0)
203                 return -EINVAL;
204
205         /* get sound file path */
206         cur_path = get_data(pattern);
207         if (!cur_path) {
208                 _E("This pattern(%s) in sound type is not supported to play",
209                                 profile->str_pattern(pattern));
210                 cur_path = "NULL";
211                 ret = -ENOENT;
212         }
213
214         snprintf(buf, buflen, "%s", cur_path);
215         return ret;
216 }
217
218 static int sound_set_path(feedback_pattern_e pattern, char *path)
219 {
220         struct stat buf;
221
222         /*
223          * check the path is valid
224          * if path is null, below operation is ignored
225          */
226         if (path && stat(path, &buf)) {
227                 _E("%s is not presents", path);
228                 return -errno;
229         }
230
231         if (sound_info.data[pattern].changed) {
232                 free(sound_info.data[pattern].changed);
233                 sound_info.data[pattern].changed = NULL;
234         }
235
236         /* if path is NULL, this pattern set to default file */
237         if (path)
238                 sound_info.data[pattern].changed = strdup(path);
239
240         _D("The file of pattern(%s) is changed to [%s]",
241                         profile->str_pattern(pattern), path);
242         return 0;
243 }
244
245 static const struct device_ops sound_device_ops = {
246         .type = FEEDBACK_TYPE_SOUND,
247         .name = "Sound",
248         .init = sound_init,
249         .exit = sound_exit,
250         .play = sound_play,
251         .is_supported = sound_is_supported,
252         .get_path = sound_get_path,
253         .set_path = sound_set_path,
254 };
255
256 DEVICE_OPS_REGISTER(&sound_device_ops);