apply alternative for no util-lib
[platform/core/api/system-settings.git] / src / sst_ringtones.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_ringtones.h"
17 #include <pthread.h>
18 #include <stdio.h>
19 #include <libgen.h>
20 #include <glib.h>
21 #include <vconf.h>
22 #include <metadata_extractor.h>
23
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_ringtone_add_incoming_call(system_settings_key_e key, void *value)
162 {
163         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         //Todo: check utc_system_settings_add_ringtone_list_p1
173         /*
174         if (false == sst_is_valid_file(path)) {
175                 ERR("Invalid ringtone file(%s)", path);
176                 sst_json_unref(handle);
177                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
178         }
179         */
180         sst_json_add_ringtone(handle, path, path);
181         sst_json_unref(handle);
182
183         return SYSTEM_SETTINGS_ERROR_NONE;
184 }
185
186 int sst_ringtone_del_incoming_call(system_settings_key_e key, void *value)
187 {
188         sst_json_h *handle = sst_json_load_ringtone();
189         sst_json_remove_ringtone(handle, value);
190         sst_json_unref(handle);
191
192         return SYSTEM_SETTINGS_ERROR_NONE;
193 }
194
195 int sst_ringtone_list_incoming_call(system_settings_key_e key, system_settings_iter_cb callback, void *data)
196 {
197         RETV_IF(NULL == callback, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
198
199         _get_default_ringtones(callback, data);
200         _get_user_ringtones(callback, data);
201
202         return SYSTEM_SETTINGS_ERROR_NONE;
203 }
204
205 int sst_ringtone_set_incoming_call(sst_interface *iface, void *value)
206 {
207         char *vconf_value = value;
208
209         bool is_valid = sst_misc_exist(vconf_value);
210         if (false == is_valid) {
211                 ERR("sst_misc_exist(%s) Fail", vconf_value);
212                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
213         }
214
215         if (vconf_set_str(iface->vconf_key, vconf_value)) {
216                 ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, vconf_value);
217                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
218         }
219
220         return SYSTEM_SETTINGS_ERROR_NONE;
221 }
222
223 int sst_ringtone_set_email_alert(sst_interface *iface, void *value)
224 {
225         char *vconf_value = value;
226
227         bool is_valid = sst_misc_exist(vconf_value);
228         if (false == is_valid) {
229                 ERR("sst_misc_exist(%s) Fail", vconf_value);
230                 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
231         }
232
233         if (vconf_set_str(iface->vconf_key, vconf_value)) {
234                 ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, vconf_value);
235                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
236         }
237
238         return SYSTEM_SETTINGS_ERROR_NONE;
239 }
240
241 /**
242  * VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR has a path of the ringtone file which user choose
243  * @return the ringtone file path specified by user in normal case
244  *                 if it's not accessable, return the default ringtone path
245  */
246 int sst_ringtone_get_incoming_call(sst_interface *iface, void **value)
247 {
248         char *vconf_value = NULL;
249         if (sst_vconf_get_string(iface->vconf_key, &vconf_value))
250                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
251
252         /* check to see if it's accessable -> OK */
253         /* no --> default ringtone path VCONFKEY_SETAPPL_CALL_RINGTONE_DEFAULT_PATH_STR */
254         bool is_valid = sst_misc_exist(vconf_value);
255         if (true == is_valid) {
256                 *value = vconf_value;
257         } else {
258                 *value = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_DEFAULT_PATH_STR);
259                 free(vconf_value);
260         }
261
262         return SYSTEM_SETTINGS_ERROR_NONE;
263 }
264
265 int sst_ringtone_get_email_alert(sst_interface *iface, void **value)
266 {
267         char *vconf_value = NULL;
268         if (sst_vconf_get_string(iface->vconf_key, &vconf_value))
269                 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
270
271         /* check to see if it's accessable -> OK */
272         /* no --> default ringtone path VCONFKEY_SETAPPL_NOTI_RINGTONE_DEFAULT_PATH_STR */
273         bool is_valid = sst_misc_exist(vconf_value);
274         if (true == is_valid) {
275                 *value = vconf_value;
276         } else {
277                 *value = vconf_get_str(VCONFKEY_SETAPPL_NOTI_RINGTONE_DEFAULT_PATH_STR);
278                 free(vconf_value);
279         }
280
281         return SYSTEM_SETTINGS_ERROR_NONE;
282 }