sound: Support multi-theme sound conf usage 81/296981/1
authorYunhee Seo <yuni.seo@samsung.com>
Tue, 1 Aug 2023 06:23:52 +0000 (15:23 +0900)
committerYunhee Seo <yuni.seo@samsung.com>
Tue, 8 Aug 2023 07:56:39 +0000 (16:56 +0900)
Allows users to select one of several theme files.
Conf file detailed usage is explained in the common/data/sound.conf file.

Example of conf file usage
[SoundMultiTheme] -> It means support multi theme
number_of_theme=2 -> It means how many confs are supported
name_of_default_theme=SoundTheme2 -> It means SoundTheme2 section file is set to default conf
[SoundTheme1] -> Match the conf file number and file path
file_path_of_theme=/usr/share/feedback/sound-theme1.conf
[SoundTheme2]
file_path_of_theme=/usr/share/feedback/sound-theme2.conf

To support this, below functions are newly added to feedback-internal.h.
- int feedback_get_count_of_theme_internal(feedback_type_e feedback_type, unsigned int *count_of_theme);
    - This function gets the number of theme described in the config file.
- int feedback_get_theme_index_internal(feedback_type_e feedback_type, unsigned int *index_of_theme);
    - This function gets the current index of theme selected.
- int feedback_set_theme_index_internal(feedback_type_e feedback_type, unsigned int index_of_theme);
    - This function sets the index of theme will be used.
      After that, It is possible to use the feedback files defined in the theme(index_of_theme) conf file.

In deed, this patch only supports sound theme.

Change-Id: Idd25bed7b091fffe6d9c7a5729a670f0f27469c4
Signed-off-by: Yunhee Seo <yuni.seo@samsung.com>
common/data/sound.conf
include/feedback-internal.h
src/devices.h
src/feedback-config.c
src/feedback.c
src/sound.c
src/vibrator.c

index c7adc96..5e896b3 100644 (file)
@@ -1,3 +1,34 @@
+# [SoundMultiTheme]
+# - As put this section, This means this conf file supports multi theme.
+#   Thus if you define this section, please remove [Sound] section in this file.
+#   It cannot be defined together, so put [Sound] section to another conf files alone.
+#   Furthermore, this section must be located sound.conf(default file).
+#   If you define this section to another file, it will be not work properly.
+#   If you do not define this section in this file, then default theme number will be 0.
+#   It means if you define [SoundMultiTheme], you cannot use 0 as theme index.
+#   And also [Sound] will be parsed and used like the existing operation.
+#  number_of_theme=int(range=1~N)
+#   - Define how many conf file will be used.
+#     The number_of_theme should be start with 1 to N.
+#  name_of_default_theme=string
+#   - Define default theme conf file as put SoundThemeN name, The N number file will be selected
+#     as a default theme conf file.
+#     The N number range=1~N
+# [SoundThemeN]
+# - This section determines that the file is defined as the Nth theme.
+#  file_path_of_theme=string
+#   - Defines the path of the corresponding number file.
+#     In this file, [Sound] section and new patterns, new files should be defined.
+#
+# Example
+# [SoundMultiTheme]
+# number_of_theme=2
+# name_of_default_theme=SoundTheme2
+# [SoundTheme1]
+# file_path_of_theme=/usr/share/feedback/sound-theme1.conf
+# [SoundTheme2]
+# file_path_of_theme=/usr/share/feedback/sound-theme2.conf
+
 [Sound]
 FEEDBACK_PATTERN_TAP=/usr/share/feedback/sound/touch/touch.wav
 FEEDBACK_PATTERN_SIP=/usr/share/feedback/sound/touch/sip.wav
index cbf670d..559196e 100755 (executable)
@@ -158,6 +158,53 @@ int feedback_play_type_internal(feedback_type_e type, feedback_pattern_internal_
 int feedback_play_type_soundpath_internal(feedback_type_e type, feedback_pattern_internal_e internal_pattern, const char *soundpath);
 
 /**
+ * @brief Gets the number of theme supported.
+ * @details This function gets the number of theme described in the config file.
+ * @since_tizen 8.0
+ * @param[in] type The feedback type
+ * @param[out] count_of_theme The number of theme supported
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #FEEDBACK_ERROR_NONE Successful
+ * @retval #FEEDBACK_ERROR_OPERATION_FAILED Operation not permitted
+ * @retval #FEEDBACK_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #FEEDBACK_ERROR_NOT_SUPPORTED Not supported device
+ * @retval #FEEDBACK_ERROR_NOT_INITIALIZED Not initialized
+ * @pre feedback_initialize()
+ */
+int feedback_get_count_of_theme_internal(feedback_type_e feedback_type, unsigned int *count_of_theme);
+
+/**
+ * @brief Gets the current index of theme selected.
+ * @details This function gets the current index of theme selected.
+ * @since_tizen 8.0
+ * @param[in] type The feedback type
+ * @param[out] index_of_theme The current index of theme selected
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #FEEDBACK_ERROR_NONE Successful
+ * @retval #FEEDBACK_ERROR_OPERATION_FAILED Operation not permitted
+ * @retval #FEEDBACK_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #FEEDBACK_ERROR_NOT_SUPPORTED Not supported device
+ */
+int feedback_get_theme_index_internal(feedback_type_e feedback_type, unsigned int *index_of_theme);
+
+/**
+ * @brief Sets the current index of theme.
+ * @details This function sets the index of theme.
+ * @since_tizen 8.0
+ * @param[in] type The feedback type
+ * @param[in] index_of_theme The index of theme will be selected
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #FEEDBACK_ERROR_NONE Successful
+ * @retval #FEEDBACK_ERROR_OPERATION_FAILED Operation not permitted
+ * @retval #FEEDBACK_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #FEEDBACK_ERROR_NOT_SUPPORTED Not supported device
+ */
+int feedback_set_theme_index_internal(feedback_type_e feedback_type, unsigned int index_of_theme);
+
+/**
  * @}
  */
 
index 0e8cb61..6a9aedb 100644 (file)
@@ -34,6 +34,9 @@ struct device_ops {
        int (*is_supported) (int, bool *);
        int (*get_path) (int, char *, unsigned int);
        int (*set_path) (int, char *);
+       int (*get_count_of_theme) (unsigned int *);
+       int (*get_theme_index) (unsigned int *);
+       int (*set_theme_index) (unsigned int);
 };
 
 void devices_init(void);
index d75a9bb..3be32fc 100644 (file)
@@ -84,6 +84,7 @@ int feedback_load_config(const char *path,
        for (i = 0; i < profile->get_num_of_pattern(); i++)
                info->data[i].pattern = -1;
 
+       load_config_index = 0;
        ret = config_parse(path, load_config, info);
        if (ret < 0)
                _E("Failed to load %s, %d Use default value!", //LCOV_EXCL_LINE
index d3b3972..dd5d254 100644 (file)
@@ -523,3 +523,93 @@ API int feedback_play_type_soundpath_internal(feedback_type_e type, feedback_pat
 
        return FEEDBACK_ERROR_NONE;
 }
+
+API int feedback_get_count_of_theme_internal(feedback_type_e feedback_type, unsigned int *count_of_theme)
+{
+       const struct device_ops *dev = NULL;
+       int ret = 0;
+
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+       pthread_mutex_unlock(&fmutex);
+
+       if (feedback_type <= FEEDBACK_TYPE_NONE || feedback_type >= profile->max_type || !count_of_theme) {
+               _E("Invalid parameter : type(%d)", feedback_type);
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
+       }
+
+       dev = find_device(feedback_type);
+       if (!dev) {
+               _E("Not supported device : type(%s)", profile->str_type[feedback_type]);
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       }
+
+       if (!dev->get_count_of_theme)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+
+       ret = dev->get_count_of_theme(count_of_theme);
+       if (ret < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
+       return FEEDBACK_ERROR_NONE;
+}
+
+API int feedback_get_theme_index_internal(feedback_type_e feedback_type, unsigned int *index_of_theme)
+{
+       const struct device_ops *dev = NULL;
+       int ret = 0;
+
+       if (feedback_type <= FEEDBACK_TYPE_NONE || feedback_type >= profile->max_type || !index_of_theme) {
+               _E("Invalid parameter : type(%d)", feedback_type);
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
+       }
+
+       dev = find_device(feedback_type);
+       if (!dev) {
+               _E("Not supported device : type(%s)", profile->str_type[feedback_type]);
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       }
+
+       if (!dev->get_theme_index)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+
+       pthread_mutex_lock(&fmutex);
+       ret = dev->get_theme_index(index_of_theme);
+       pthread_mutex_unlock(&fmutex);
+       if (ret < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
+       return FEEDBACK_ERROR_NONE;
+}
+
+API int feedback_set_theme_index_internal(feedback_type_e feedback_type, unsigned int index_of_theme)
+{
+       const struct device_ops *dev = NULL;
+       int ret = 0;
+
+       if (feedback_type <= FEEDBACK_TYPE_NONE || feedback_type >= profile->max_type) {
+               _E("Invalid parameter : type(%d)", feedback_type);
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
+       }
+
+       dev = find_device(feedback_type);
+       if (!dev) {
+               _E("Not supported device : type(%s)", profile->str_type[feedback_type]);
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       }
+
+       if (!dev->set_theme_index)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+
+       pthread_mutex_lock(&fmutex);
+       ret = dev->set_theme_index(index_of_theme);
+       pthread_mutex_unlock(&fmutex);
+       if (ret < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
+       return FEEDBACK_ERROR_NONE;
+}
index e2fc1a1..ee577a2 100644 (file)
@@ -29,6 +29,8 @@
 #include <mm_sound_private.h>
 #include <sound_manager.h>
 #include <wav_player.h>
+#include <libsyscommon/ini-parser.h>
+#include <libsyscommon/list.h>
 
 #include "feedback-ids.h"
 #include "profiles.h"
@@ -37,7 +39,7 @@
 #include "feedback-config.h"
 
 #define SOUND_CONF_FILE FEEDBACK_SYS_RO_SHARE"/feedback/sound.conf"
-
+#define SOUND_NAME                             "Sound"
 /* Temporary keys */
 #ifndef VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL
 #define VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL "db/setting/sound/button_sounds"
@@ -46,9 +48,9 @@
 static int sndstatus;
 static int touch_sndstatus;
 static int keytone_sndstatus;
-static struct feedback_config_info sound_info = {
-       .name = "Sound",
-};
+static int current_theme_index = 0;
+static int number_of_theme = 0;
+static struct feedback_config_info *sound_info;
 
 static char *get_data(feedback_pattern_e pattern)
 {
@@ -65,7 +67,7 @@ static char *get_data(feedback_pattern_e pattern)
                return data;
 
        for (i = 0; i < profile->get_num_of_pattern(); i++) {
-               if (pattern == sound_info.data[i].pattern) {
+               if (pattern == sound_info[current_theme_index].data[i].pattern) {
                        index = i;
                        break;
                }
@@ -75,10 +77,10 @@ static char *get_data(feedback_pattern_e pattern)
                return NULL;
        }
 
-       if (sound_info.data[index].changed)
-               data = sound_info.data[index].changed;
+       if (sound_info[current_theme_index].data[index].changed)
+               data = sound_info[current_theme_index].data[index].changed;
        else
-               data = sound_info.data[index].origin;
+               data = sound_info[current_theme_index].data[index].origin;
 
        return data;
 }
@@ -115,12 +117,132 @@ static void feedback_keytone_sndstatus_cb(keynode_t *key, void* data)
 }
 //LCOV_EXCL_STOP
 
+static int feedback_parse_sound_multi_theme_section(const struct parse_result *result, void *data)
+{
+       struct section_property *extracted_section_prop = NULL;
+       GList *temp_glist = NULL;
+
+       if (!result || !result->props)
+               return 0;
+
+       if (!MATCH("SoundMultiTheme", result->section))
+               return 0;
+
+       SYS_G_LIST_FOREACH(result->props, temp_glist, extracted_section_prop) {
+               if (MATCH("number_of_theme", extracted_section_prop->key)) {
+                       sscanf(extracted_section_prop->value, "%d", &number_of_theme);
+               } else if (MATCH("name_of_default_theme", extracted_section_prop->key)) {
+                       sscanf(extracted_section_prop->value, "SoundTheme%d", &current_theme_index);
+               } else {
+                       _E("Failed to parse SoundMultiTheme section. Please check your config file, \
+                               check the value or typo of key value");
+                       return -EINVAL;
+               }
+       }
+
+       if (number_of_theme < current_theme_index) {
+               _E("Failed to parse SoundMultiTheme section. Please check your config file, \
+                       default theme number cannot be greater then the number of theme");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static bool feedback_is_multi_theme_support(const char *path)
+{
+       int ret = 0;
+
+       if (!path)
+               return false;
+
+       ret = syscommon_config_parse_by_section(path, feedback_parse_sound_multi_theme_section, NULL);
+       if (ret < 0)
+               return false;
+
+       if (number_of_theme > 0)
+               return true;
+
+       return false;
+}
+
+static int feedback_parse_multi_theme_conf_path_section(const struct parse_result *result, void *data)
+{
+       struct section_property *extracted_section_prop = NULL;
+       GList *temp_glist = NULL;
+       int multi_theme_index = 0;
+       int ret = 0;
+
+       if (!result || !result->props)
+               return 0;
+
+       if (!strstr(result->section, "SoundTheme"))
+               return 0;
+
+       ret = sscanf(result->section, "SoundTheme%d", &multi_theme_index);
+       if (ret == EOF)
+               return 0;
+
+       if (multi_theme_index < 0 || multi_theme_index > number_of_theme)
+               return 0;
+
+       SYS_G_LIST_FOREACH(result->props, temp_glist, extracted_section_prop) {
+               if (MATCH("file_path_of_theme", extracted_section_prop->key)) {
+                       feedback_load_config(extracted_section_prop->value, &sound_info[multi_theme_index]);
+               } else {
+                       _E("Failed to parse SoundThemeN section, Please check your config file, \
+                               check the value or typo of key value");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int feedback_multi_theme_load_config(const char *path)
+{
+       int ret = 0;
+
+       if (!path)
+               return -EINVAL;
+
+       ret = syscommon_config_parse_by_section(path, feedback_parse_multi_theme_conf_path_section, NULL);
+
+       return ret;
+}
+
+static int sound_get_config(void)
+{
+       bool is_support_multi_theme = false;
+
+       is_support_multi_theme = feedback_is_multi_theme_support(SOUND_CONF_FILE);
+
+       sound_info = (struct feedback_config_info*)calloc(number_of_theme+1, sizeof(struct feedback_config_info));
+       if (!sound_info) {
+               _E("Failed to allocate memory for sound_info.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i <= number_of_theme; i++)
+               sound_info[i].name = SOUND_NAME;
+
+       if (is_support_multi_theme) {
+               feedback_multi_theme_load_config(SOUND_CONF_FILE);
+       } else {
+               current_theme_index = 0;
+               feedback_load_config(SOUND_CONF_FILE, &sound_info[current_theme_index]);
+       }
+
+       return 0;
+}
+
 static void sound_init(void)
 {
-       int ret;
+       int ret = 0;
 
-       /* get sound data */
-       feedback_load_config(SOUND_CONF_FILE, &sound_info);
+       ret = sound_get_config();
+       if (ret < 0)
+               _W("Failed to load configuration file(%s): %d", SOUND_CONF_FILE, ret);
 
        /* check sound status */
        if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0)
@@ -146,6 +268,18 @@ static void sound_init(void)
                _W("Add watch for VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL failed"); //LCOV_EXCL_LINE
 }
 
+static void sound_put_config(void)
+{
+       if (!sound_info)
+               return;
+
+       /* free sound data */
+       for (int i = 0; i <= number_of_theme; i++) {
+               feedback_free_config(&sound_info[i]);
+       }
+       sound_info = NULL;
+}
+
 static void sound_exit(void)
 {
        int ret;
@@ -162,8 +296,7 @@ static void sound_exit(void)
        if (ret != 0)
                _W("Remove watch for VCONFKEY_SETAPPL_BUTTON_SOUNDS_BOOL failed"); //LCOV_EXCL_LINE
 
-       /* free sound data */
-       feedback_free_config(&sound_info);
+       sound_put_config();
 }
 
 //LCOV_EXCL_START
@@ -406,7 +539,7 @@ static int sound_set_path(feedback_pattern_e pattern, char *path)
        }
 
        for (i = 0; i < profile->get_num_of_pattern(); i++) {
-               if (pattern == sound_info.data[i].pattern) {
+               if (pattern == sound_info[current_theme_index].data[i].pattern) {
                        index = i;
                        break;
                }
@@ -414,14 +547,14 @@ static int sound_set_path(feedback_pattern_e pattern, char *path)
 
        if (index < 0) {
                for (i = 0; i < profile->get_num_of_pattern(); i++) {
-                       if (sound_info.data[i].pattern != -1)
+                       if (sound_info[current_theme_index].data[i].pattern != -1)
                                continue;
 
-                       sound_info.data[i].pattern = pattern;
+                       sound_info[current_theme_index].data[i].pattern = pattern;
                        if (path)
-                               sound_info.data[i].changed = strdup(path);
+                               sound_info[current_theme_index].data[i].changed = strdup(path);
                        else
-                               sound_info.data[i].changed = NULL;
+                               sound_info[current_theme_index].data[i].changed = NULL;
 
                        _D("The file of pattern(%s) is changed to [%s]",
                                        profile->str_pattern(pattern), path? path:"NULL");
@@ -432,14 +565,14 @@ static int sound_set_path(feedback_pattern_e pattern, char *path)
                return -EPERM;
        }
 
-       if (sound_info.data[index].changed) {
-               free(sound_info.data[index].changed);
-               sound_info.data[index].changed = NULL;
+       if (sound_info[current_theme_index].data[index].changed) {
+               free(sound_info[current_theme_index].data[index].changed);
+               sound_info[current_theme_index].data[index].changed = NULL;
        }
 
        /* if path is NULL, this pattern set to default file */
        if (path)
-               sound_info.data[index].changed = strdup(path);
+               sound_info[current_theme_index].data[index].changed = strdup(path);
 
        _D("The file of pattern(%s) is changed to [%s]",
                        profile->str_pattern(pattern), path);
@@ -447,6 +580,39 @@ static int sound_set_path(feedback_pattern_e pattern, char *path)
 }
 //LCOV_EXCL_STOP
 
+static int sound_get_count_of_theme(unsigned int *count_of_theme)
+{
+       if (!count_of_theme)
+               return -EINVAL;
+
+       *count_of_theme = number_of_theme;
+
+       return 0;
+}
+
+static int sound_get_theme_index(unsigned int *index_of_theme)
+{
+       if (!index_of_theme)
+               return -EINVAL;
+
+       *index_of_theme = current_theme_index;
+
+       return 0;
+}
+
+static int sound_set_theme_index(unsigned int index_of_theme)
+{
+       if (index_of_theme > number_of_theme)
+               return -EINVAL;
+
+       if (number_of_theme > 0 && index_of_theme == 0)
+               return -EINVAL;
+
+       current_theme_index = index_of_theme;
+
+       return 0;
+}
+
 static const struct device_ops sound_device_ops = {
        .type = FEEDBACK_TYPE_SOUND,
        .name = "Sound",
@@ -458,6 +624,9 @@ static const struct device_ops sound_device_ops = {
        .is_supported = sound_is_supported,
        .get_path = sound_get_path,
        .set_path = sound_set_path,
+       .get_count_of_theme = sound_get_count_of_theme,
+       .get_theme_index = sound_get_theme_index,
+       .set_theme_index = sound_set_theme_index,
 };
 
 DEVICE_OPS_REGISTER(&sound_device_ops);
index 7baf50d..7ad95c5 100644 (file)
@@ -375,6 +375,9 @@ static const struct device_ops vibrator_device_ops = {
        .is_supported = vibrator_is_supported,
        .get_path = vibrator_get_path,
        .set_path = vibrator_set_path,
+       .get_count_of_theme = NULL,
+       .set_theme_index = NULL,
+       .get_theme_index = NULL,
 };
 
 DEVICE_OPS_REGISTER(&vibrator_device_ops);