Add unit test to increase coverage
[platform/core/api/system-settings.git] / src / sst_sound.c
1 /*
2  * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include "sst_sound.h"
17
18 #include <stdio.h>
19 #include <pthread.h>
20 #include <libgen.h>
21 #include <glib.h>
22 #include <vconf.h>
23 #include <metadata_extractor.h>
24 #include "sst.h"
25 #include "sst_json.h"
26 #include "sst_vconf.h"
27 #include "sst_misc.h"
28 #include "sst_interface.h"
29
30 typedef struct _file_Info {
31         char *name;
32         char *media_name;
33 } sst_file_info;
34
35 static char* get_media_basename(const char *dir_path, const char *name)
36 {
37         RETV_IF(NULL == name, NULL);
38         RETV_IF(NULL == dir_path, NULL);
39
40         char path[PATH_MAX];
41         snprintf(path, sizeof(path), "%s/%s", dir_path, name);
42
43         metadata_extractor_h metadata = NULL;
44         int ret = metadata_extractor_create(&metadata);
45         if (ret != METADATA_EXTRACTOR_ERROR_NONE || NULL == metadata) {
46                 ERR("metadata_extractor_create() Fail(%d)", ret);
47                 return strdup(name);
48         }
49
50         ret = metadata_extractor_set_path(metadata, path);
51         if (METADATA_EXTRACTOR_ERROR_NONE != ret) {
52                 ERR("metadata_extractor_set_path(%s) Fail(%d)", path, ret);
53                 metadata_extractor_destroy(metadata);
54                 return strdup(name);
55         }
56
57         char *title = NULL;
58         ret = metadata_extractor_get_metadata(metadata, METADATA_TITLE, &title);
59         metadata_extractor_destroy(metadata);
60         if (title)
61                 return title;
62         else
63                 return strdup(name);
64 }
65
66 static int _get_filelist_in_dir(const char *path, GList **file_list)
67 {
68         DIR *dir;
69         struct dirent *ent;
70         static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
71
72         RETV_IF(NULL == path, -1);
73         RETV_IF(NULL == file_list, -1);
74
75         dir = opendir(path);
76         if (NULL == dir) {
77                 ERR("opendir(%s) Fail(%d)", path, errno);
78                 return -2;
79         }
80
81         pthread_mutex_lock(&mutex);
82         while ((ent = readdir(dir)) != NULL) {
83                 if (strncmp(ent->d_name, ".", 1) == 0 || strcmp(ent->d_name, "..") == 0)
84                         continue;
85
86                 if ((ent->d_type & DT_REG) == 0)
87                         continue;
88
89                 sst_file_info *info = calloc(1, sizeof(sst_file_info));
90                 if (NULL == info) {
91                         ERR("calloc() Fail(%d)", errno);
92                         break;
93                 }
94
95                 info->name = strdup(ent->d_name);
96                 info->media_name = get_media_basename(path, info->name);
97
98                 *file_list = g_list_append(*file_list, info);
99         }
100         pthread_mutex_unlock(&mutex);
101
102         closedir(dir);
103         return 0;
104 }
105
106 static gint _ringtone_compare_cb(gconstpointer a, gconstpointer b)
107 {
108         const sst_file_info *info1 = a;
109         const sst_file_info *info2 = b;
110
111         return strcmp(info1->media_name, info2->media_name);
112 }
113
114 static void _get_default_ringtones(system_settings_iter_cb callback, void *data)
115 {
116         RET_IF(NULL == callback);
117
118         GList *filelist = NULL;
119         sst_file_info *info;
120         int idx = 0;
121
122         const char *ringtone_dir = SST_DEFAULT_RINGTONE_DIR;
123         int ret = _get_filelist_in_dir(ringtone_dir, &filelist);
124         if (ret != 0) {
125                 ERR("_get_filelist_in_dir(%s) Fail(%d)", ringtone_dir, ret);
126                 return;
127         }
128
129         filelist = g_list_sort(filelist, _ringtone_compare_cb);
130
131         GList *cur;
132         for (cur = filelist; cur; cur = cur->next) {
133                 info = cur->data;
134
135                 char fullpath[PATH_MAX];
136                 snprintf(fullpath, sizeof(fullpath), "%s/%s", ringtone_dir, info->name);
137                 bool ret = callback(idx, fullpath, data);
138                 if (ret == false) {
139                         ERR("callback return false");
140                         break;
141                 }
142         }
143
144         for (cur = filelist; cur; cur = cur->next) {
145                 info = cur->data;
146                 free(info->name);
147                 free(info->media_name);
148                 free(info);
149         }
150         g_list_free(filelist);
151 }
152
153 static void _get_user_ringtones(system_settings_iter_cb callback, void *user_data)
154 {
155         RET_IF(NULL == callback);
156
157         sst_json_h *handle = sst_json_load_ringtone();
158         sst_json_get_ringtones(handle, callback, user_data);
159         sst_json_unref(handle);
160 }
161 int sst_sound_add_call_ringtone(system_settings_key_e key, const char *value)
162 {
163         const char *path = value;
164         sst_json_h *handle = sst_json_load_ringtone();
165
166         if (sst_json_contain_ringtone(handle, path)) {
167                 ERR("ringtone(%s) is duplicated", path);
168                 sst_json_unref(handle);
169                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
170         }
171
172         if (false == sst_misc_file_exists(path)) {
173                 ERR("sst_misc_file_exists(%s) Fail", path);
174                 sst_json_unref(handle);
175                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
176         }
177
178         sst_json_add_ringtone(handle, path, path);
179         sst_json_unref(handle);
180
181         return SYSTEM_SETTINGS_ERROR_NONE;
182 }
183
184 int sst_sound_del_call_ringtone(system_settings_key_e key, const char *value)
185 {
186         sst_json_h *handle = sst_json_load_ringtone();
187         sst_json_remove_ringtone(handle, value);
188         sst_json_unref(handle);
189
190         return SYSTEM_SETTINGS_ERROR_NONE;
191 }
192
193 int sst_sound_get_call_ringtone_list(system_settings_key_e key, system_settings_iter_cb callback, void *data)
194 {
195         RETV_IF(NULL == callback, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
196
197         _get_default_ringtones(callback, data);
198         _get_user_ringtones(callback, data);
199
200         return SYSTEM_SETTINGS_ERROR_NONE;
201 }
202
203 int sst_sound_set_call_ringtone(sst_interface *iface, const char *value)
204 {
205         bool is_valid = sst_misc_file_exists(value);
206         if (false == is_valid) {
207                 ERR("sst_misc_file_exists(%s) Fail", value);
208                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
209         }
210
211         if (vconf_set_str(iface->vconf_key, value)) {
212                 ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, value);
213                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
214         }
215
216         return SYSTEM_SETTINGS_ERROR_NONE;
217 }
218
219 int sst_sound_set_email_alert(sst_interface *iface, const char *value)
220 {
221         bool is_valid = sst_misc_file_exists(value);
222         if (false == is_valid) {
223                 ERR("sst_misc_file_exists(%s) Fail", value);
224                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
225         }
226
227         if (vconf_set_str(iface->vconf_key, value)) {
228                 ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, value);
229                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
230         }
231
232         return SYSTEM_SETTINGS_ERROR_NONE;
233 }
234
235 /**
236  * VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR has a path of the ringtone file which user choose
237  * @return the ringtone file path specified by user in normal case
238  *                 if it's not accessable, return the default ringtone path
239  */
240 int sst_sound_get_call_ringtone(sst_interface *iface, char **value)
241 {
242         char *vconf_value = NULL;
243         if (sst_vconf_get_str_ally(iface->vconf_key, &vconf_value))
244                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
245
246         /* check to see if it's accessable -> OK */
247         /* no --> default ringtone path VCONFKEY_SETAPPL_CALL_RINGTONE_DEFAULT_PATH_STR */
248         bool is_valid = sst_misc_file_exists(vconf_value);
249         if (true == is_valid) {
250                 *value = vconf_value;
251         } else {
252                 *value = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_DEFAULT_PATH_STR);
253                 free(vconf_value);
254         }
255
256         return SYSTEM_SETTINGS_ERROR_NONE;
257 }
258
259 int sst_sound_get_email_alert(sst_interface *iface, char **value)
260 {
261         char *vconf_value = NULL;
262         if (sst_vconf_get_str_ally(iface->vconf_key, &vconf_value))
263                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
264
265         /* check to see if it's accessable -> OK */
266         /* no --> default ringtone path VCONFKEY_SETAPPL_NOTI_RINGTONE_DEFAULT_PATH_STR */
267         bool is_valid = sst_misc_file_exists(vconf_value);
268         if (true == is_valid) {
269                 *value = vconf_value;
270         } else {
271                 *value = vconf_get_str(VCONFKEY_SETAPPL_NOTI_RINGTONE_DEFAULT_PATH_STR);
272                 free(vconf_value);
273         }
274
275         return SYSTEM_SETTINGS_ERROR_NONE;
276 }
277
278 /**
279  * sound == false, vibration == false --> silent mode
280  * sound == true, vibration == false --> sound mode
281  * sound == false, vibration == true --> vibration mode
282  */
283 int sst_sound_get_silent_mode(sst_interface *iface, bool *value)
284 {
285         int sound_status = 0;
286         if (VCONF_OK != vconf_get_bool(iface->vconf_key, &sound_status)) {
287                 ERR("vconf_get_bool(%s) Fail", iface->vconf_key);
288                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
289         }
290
291         const char *vibration_key = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;
292         int vib_status = 0;
293         if (VCONF_OK != vconf_get_bool(vibration_key, &vib_status)) {
294                 ERR("vconf_get_bool(%s) Fail", vibration_key);
295                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
296         }
297
298         bool result = (sound_status == FALSE && vib_status == FALSE);
299         *value = result;
300
301         return SYSTEM_SETTINGS_ERROR_NONE;
302 }
303
304 /**
305  * sound == false, vibration == false --> silent mode
306  * sound == true, vibration == false --> sound mode
307  */
308 //Todo: It should return to the old status.
309 int sst_sound_set_silent_mode(sst_interface *iface, bool value)
310 {
311         int sound_state = !value;
312         if (vconf_set_bool(iface->vconf_key, sound_state)) {
313                 ERR("vconf_set_bool(%s, %d) Fail", iface->vconf_key, sound_state);
314                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
315         }
316
317         int vib_state = FALSE;
318         const char *vibration_key = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;
319         if (vconf_set_bool(vibration_key, vib_state)) {
320                 ERR("vconf_set_bool(%s) Fail", vibration_key);
321                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
322         }
323
324         return SYSTEM_SETTINGS_ERROR_NONE;
325 }
326
327 int sst_sound_set_notification(sst_interface *iface, const char *value)
328 {
329         bool is_valid = sst_misc_file_exists(value);
330         if (true == is_valid) {
331                 if (vconf_set_str(iface->vconf_key, value)) {
332                         ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, value);
333                         return SYSTEM_SETTINGS_ERROR_IO_ERROR;
334                 }
335         } else {
336                 ERR("sst_misc_file_exists(%s) Fail", value);
337                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
338         }
339
340         return SYSTEM_SETTINGS_ERROR_NONE;
341 }