To support sound play with priority, new api is added.
This function is added to feedback.
- int feedback_play_type_with_flags_internal(feedback_type_e type, feedback_pattern_internal_e internal_pattern,
feedback_flag_e flag);
- This function plays feedback pattern by pre-defined feedback_flag_e.
Sound play behavior varies depending on feedback_flag_e.
- FEEDBACK_FLAG_NONE
- This flag works the same as feedback_play_type_internal().
- FEEDBACK_FLAG_PRIORITY_BASED_PLAY
- This flag will only work in sound play. Sound pattern will be played with priority.
The sound pattern priority value will be used as defined in the sound conf file.
Change-Id: Idba5314030d393af82d155cd8e4a258a9e6ab82f
Signed-off-by: Yunhee Seo <yuni.seo@samsung.com>
#define FEEDBACK_FAILED(n) ((n) != FEEDBACK_ERROR_NONE)
/**
+ * @brief Enumeration for feedback sound play method.
+ * @details Currently, it is used only in the sound play.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ FEEDBACK_FLAG_NONE = 0, /**< Feedback flag none */
+ FEEDBACK_FLAG_PRIORITY_BASED_PLAY = (1<<0), /**< Feedback flag for priority-based play */
+} feedback_flag_e;
+
+/**
*
* @brief Plays specific type of reactions that are pre-defined.
* @details
int feedback_get_theme_ids_internal(feedback_type_e feedback_type, unsigned int *count_of_theme, unsigned int **theme_ids);
/**
+ * @brief Plays specific type of reactions that are pre-defined with priority.
+ * @details This function can be used to react to pre-defined actions. \n
+ * It play specific type of system pre-defined pattern with priority.
+ * @since_tizen 7.0
+ * @remarks Currently, there are two types of reactions: sound and vibration. \n
+ * Depending on the settings, some types cannot be operated.
+ * FEEDBACK_FLAG_PRIORITY_BASED_PLAY is for playing sound with priority.
+ * FEEDBACK_FLAG_NONE works the same as feedback_play_type_internal().
+ * And for controlling haptic device, the privilege should be set to, %http://tizen.org/privilege/haptic.
+ * If you don't have the haptic privilege, it returns FEEDBACK_ERROR_PERMISSION_DENIED error.
+ * The above-mentioned haptic device rule is only for FEEDBACK_FLAG_NONE.
+ * Priority playing is not supported in vibrator.
+ * @param[in] type The pattern type
+ * @param[in] pattern The pre-defined internal pattern
+ * @param[in] flag The sound play method flag
+ * @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_PERMISSION_DENIED Permission denied
+ * @retval #FEEDBACK_ERROR_NOT_INITIALIZED Not initialized
+ * @pre feedback_initialize()
+ * @see feedback_play_type_internal()
+ */
+int feedback_play_type_with_flags_internal(feedback_type_e type, feedback_pattern_internal_e internal_pattern, feedback_flag_e flag);
+/**
* @}
*/
void (*exit) (void);
int (*play) (int, bool);
int (*play_path) (int, const char *, bool);
+ int (*play_with_priority) (int, bool);
int (*stop) (void);
int (*is_supported) (int, bool *);
int (*get_path) (int, char *, unsigned int);
return FEEDBACK_ERROR_NONE;
}
+
+API int feedback_play_type_with_flags_internal(feedback_type_e type, feedback_pattern_internal_e internal_pattern, feedback_flag_e flag)
+{
+ const struct device_ops *dev;
+ int err;
+ feedback_pattern_e pattern = (feedback_pattern_e)internal_pattern;
+
+ if (flag < FEEDBACK_FLAG_NONE || flag > FEEDBACK_FLAG_PRIORITY_BASED_PLAY) {
+ _E("Invalid parameter : feedback_flag_e(%d)", flag);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ if (flag == FEEDBACK_FLAG_NONE)
+ return feedback_play_type_internal(type, internal_pattern);
+
+ /* check initialize */
+ 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 (type <= FEEDBACK_TYPE_NONE || type >= profile->max_type) {
+ _E("Invalid parameter : type(%d)", type);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= profile->max_pattern) {
+ _E("Invalid parameter : pattern(%d)", pattern);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ /* play proper device */
+ dev = find_device(type);
+ if (!dev) {
+ _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
+ return FEEDBACK_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE
+ }
+ _D("request type %s with pattern %s(%d)", profile->str_type[type], profile->str_pattern(pattern), pattern);
+ if (flag == FEEDBACK_FLAG_PRIORITY_BASED_PLAY) {
+ if (!dev->play_with_priority)
+ return FEEDBACK_ERROR_OPERATION_FAILED;
+ err = dev->play_with_priority(check_pattern(type, pattern, __func__), true);
+ if (err == -ENOTSUP)
+ return FEEDBACK_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE
+ else if (err == -ECOMM || err == -EACCES)
+ return FEEDBACK_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
+ else if (err < 0)
+ return FEEDBACK_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
+ }
+
+ return FEEDBACK_ERROR_NONE;
+}
return sound_data->path;
}
+static int get_sound_pattern_data(feedback_pattern_e pattern, const char **path, int *priority)
+{
+ struct sound_pattern_data *sound_data = NULL;
+ int ret = 0;
+
+ if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= profile->max_pattern)
+ return -EINVAL;
+
+ ret = sound_thememan_get_pattern_data(current_theme_id, pattern, &sound_data);
+ if (ret < 0)
+ return -EPERM;
+
+ if (!sound_data) {
+ _E("Not supported pattern : %d", pattern);
+ return -EPERM;
+ }
+
+ if (sound_data->path && path)
+ *path = sound_data->path;
+
+ if (priority)
+ *priority = sound_data->priority;
+
+ return 0;
+}
+
inline int is_sound_mode(void)
{
return sndstatus;
return 0;
}
+static int sound_play_with_priority(feedback_pattern_e pattern, bool always)
+{
+ struct stat buf;
+ int retry = FEEDBACK_RETRY_CNT;
+ int ret = 0;
+ sound_stream_info_h stream_info;
+ const char *path = NULL;
+ int level;
+ int priority = -1;
+
+ if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) {
+ _D("fail to get sound status, will work as turning off"); //LCOV_EXCL_LINE
+ sndstatus = 0; //LCOV_EXCL_LINE
+ }
+
+ if (always) {
+ _W("Always on condition(pattern %s)", profile->str_pattern(pattern)); //LCOV_EXCL_LINE
+ goto check_pattern;
+ }
+
+ if (sndstatus == 0 && profile->get_always_alert_case && !profile->get_always_alert_case(FEEDBACK_TYPE_SOUND, pattern)) {
+ _D("Sound condition is OFF (sndstatus : %d)", sndstatus); //LCOV_EXCL_LINE
+ return 0;
+ }
+
+ if (sndstatus && profile->get_always_off_case && profile->get_always_off_case(FEEDBACK_TYPE_SOUND, pattern)) {
+ _D("Sound always off condition(pattern %s)", profile->str_pattern(pattern)); //LCOV_EXCL_LINE
+ return 0;
+ }
+
+check_pattern:
+ /* get sound file path */
+ ret = get_sound_pattern_data(pattern, &path, &priority);
+ if (ret < 0 || stat(path, &buf)) {
+ _E("Not supported sound pattern(pattern %d)", pattern); //LCOV_EXCL_LINE
+ return -ENOTSUP;
+ }
+
+ /* play sound file */
+ if (profile->is_notification_type && profile->is_notification_type(pattern)) {
+ ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_NOTIFICATION,
+ NULL, NULL, &stream_info);
+ if (ret != SOUND_MANAGER_ERROR_NONE) {
+ _E("Failed to set session to play sound(%d)", ret); //LCOV_EXCL_LINE
+ return -ENOENT; //LCOV_EXCL_LINE
+ }
+ do {
+ ret = wav_player_start_new(path, stream_info, play_completed, stream_info, NULL);
+ if (ret == WAV_PLAYER_ERROR_NONE) {
+ _D("Wav Play success! SND filename is %s", path); //LCOV_EXCL_LINE
+ return 0;
+ }
+ _E("Failed to play sound file (%d, %s)", ret, path); //LCOV_EXCL_LINE
+ } while (retry--); //LCOV_EXCL_LINE
+ } else {
+ do {
+ if (profile->get_strength_type)
+ level = profile->get_strength_type(FEEDBACK_TYPE_SOUND, pattern);
+ else
+ level = VOLUME_TYPE_SYSTEM;
+
+ ret = mm_sound_play_keysound_priority(path, level, priority);
+ if (ret == MM_ERROR_NONE) {
+ _D("Play success! %s(%s) priority %d", profile->str_pattern(pattern), path, priority);
+ return 0;
+ }
+ _E("mm_sound_play_keysound_priority() returned error(%d)", ret); //LCOV_EXCL_LINE
+ } while (retry--); //LCOV_EXCL_LINE
+ }
+ return -EPERM;
+}
+
static const struct device_ops sound_device_ops = {
.type = FEEDBACK_TYPE_SOUND,
.name = "Sound",
.exit = sound_exit,
.play = sound_play,
.play_path = sound_play_path,
+ .play_with_priority = sound_play_with_priority,
.stop = sound_stop,
.is_supported = sound_is_supported,
.get_path = sound_get_path,
.set_theme_id = NULL,
.get_theme_id = NULL,
.get_theme_ids = NULL,
+ .play_with_priority = NULL,
};
DEVICE_OPS_REGISTER(&vibrator_device_ops);
LOG_RESULT(TEST_FEEDBACK_GET_SOUND_THEME_ID_INTERNAL(), "TEST_FEEDBACK_GET_SOUND_THEME_ID_INTERNAL");
LOG_RESULT(TEST_FEEDBACK_SET_SOUND_THEME_ID_INTERNAL(), "TEST_FEEDBACK_SET_SOUND_THEME_ID_INTERNAL");
LOG_RESULT(TEST_FEEDBACK_GET_SOUND_THEME_IDS_INTERNAL(), "TEST_FEEDBACK_GET_SOUND_THEME_IDS_INTERNAL");
+ LOG_RESULT(TEST_FEEDBACK_PLAY_TYPE_WITH_FLAGS_INTERNAL(), "TEST_FEEDBACK_PLAY_TYPE_WITH_FLAGS_INTERNAL");
}
void show_usage()
REPORT_AND_RETURN();
}
+static void test_feedback_play_type_with_flags_internal(void)
+{
+ feedback_initialize();
+ RESULT(feedback_play_type_with_flags_internal(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_TAP, -1), FEEDBACK_ERROR_INVALID_PARAMETER, "invalid parameter");
+ RESULT(feedback_play_type_with_flags_internal(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_TAP, FEEDBACK_FLAG_PRIORITY_BASED_PLAY), FEEDBACK_ERROR_OPERATION_FAILED, "operation failed");
+ RESULT(feedback_play_type_with_flags_internal(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_TAP, FEEDBACK_FLAG_PRIORITY_BASED_PLAY), FEEDBACK_ERROR_NONE, "error none");
+ RESULT(feedback_play_type_with_flags_internal(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_TAP, FEEDBACK_FLAG_NONE), FEEDBACK_ERROR_NONE, "error none");
+ feedback_deinitialize();
+}
+
+bool TEST_FEEDBACK_PLAY_TYPE_WITH_FLAGS_INTERNAL(void)
+{
+ INIT();
+ test_feedback_play_type_with_flags_internal();
+ REPORT_AND_RETURN();
+}
+
void TEST_INTERNAL_INIT()
{
init_supported_pattern(FEEDBACK_TYPE_SOUND, pattern_s);
bool TEST_FEEDBACK_GET_SOUND_THEME_ID_INTERNAL(void);
bool TEST_FEEDBACK_SET_SOUND_THEME_ID_INTERNAL(void);
bool TEST_FEEDBACK_GET_SOUND_THEME_IDS_INTERNAL(void);
+bool TEST_FEEDBACK_PLAY_TYPE_WITH_FLAGS_INTERNAL(void);
void TEST_INTERNAL_INIT(void);