From a3cd0684ab541a8ff82c34eea30aa0cfddf46775 Mon Sep 17 00:00:00 2001 From: "jy910.yun" Date: Tue, 1 Oct 2013 22:58:43 +0900 Subject: [PATCH] seperate sound device from feedback internal code Change-Id: I396351854963b08f23de5bb468b9430a8cc62e54 Signed-off-by: jy910.yun --- CMakeLists.txt | 1 + include/devices.h | 9 ++ include/feedback-file.h | 96 +----------- include/feedback-internal.h | 10 ++ src/devices.c | 11 ++ src/feedback-internal.c | 131 +--------------- src/feedback.c | 48 ++++-- src/sound.c | 361 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 432 insertions(+), 235 deletions(-) create mode 100644 src/sound.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e7ff51..1fa250a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ SET(FEEDBACK_DATA_DIRS ${FEEDBACK_DATA_PATH}/feedback) SET(SRCS src/devices.c + src/sound.c src/feedback.c src/feedback-internal.c src/xmlparser.c) diff --git a/include/devices.h b/include/devices.h index 7439065..226c910 100644 --- a/include/devices.h +++ b/include/devices.h @@ -31,6 +31,15 @@ struct device_ops { void devices_init(void); void devices_exit(void); +void devices_play(int pattern); + +#ifndef __CONSTRUCTOR__ +#define __CONSTRUCTOR__ __attribute__ ((constructor)) +#endif + +#ifndef __DESTRUCTOR__ +#define __DESTRUCTOR__ __attribute__ ((destructor)) +#endif #define DEVICE_OPS_REGISTER(dev) \ static void __CONSTRUCTOR__ module_init(void) \ diff --git a/include/feedback-file.h b/include/feedback-file.h index 435be83..f7ab443 100644 --- a/include/feedback-file.h +++ b/include/feedback-file.h @@ -19,12 +19,7 @@ #ifndef __FEEDBACK_FILE_H__ #define __FEEDBACK_FILE_H__ -#define FEEDBACK_DATA_DIR "/opt/usr/share/feedback" -#define FEEDBACK_ORIGIN_DATA_DIR "/usr/share/feedback" - -#define FEEDBACK_SOUND_DIR FEEDBACK_DATA_DIR"/sound" -#define FEEDBACK_SOUND_TOUCH_DIR FEEDBACK_SOUND_DIR"/touch" -#define FEEDBACK_SOUND_OPER_DIR FEEDBACK_SOUND_DIR"/operation" +#include "feedback-internal.h" #define FEEDBACK_HAPTIC_DIR FEEDBACK_DATA_DIR"/haptic" #define FEEDBACK_HAPTIC_TOUCH_DIR FEEDBACK_HAPTIC_DIR"/touch" @@ -32,95 +27,6 @@ #define FEEDBACK_HAPTIC_NOTI_DIR FEEDBACK_HAPTIC_DIR"/notification" #define FEEDBACK_HAPTIC_DEFAULT_DIR FEEDBACK_HAPTIC_DIR"/default" -const char* snd_file[] = { - /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : GENERAL */ - FEEDBACK_SOUND_TOUCH_DIR"/touch.wav", - /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : TEXT_NUMERIC_INPUT */ - FEEDBACK_SOUND_TOUCH_DIR"/sip.wav", - FEEDBACK_SOUND_TOUCH_DIR"/sip_backspace.wav", - FEEDBACK_SOUND_TOUCH_DIR"/sip.wav", - /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : DAILER */ - FEEDBACK_SOUND_TOUCH_DIR"/key0.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key1.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key2.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key3.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key4.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key5.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key6.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key7.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key8.wav", - FEEDBACK_SOUND_TOUCH_DIR"/key9.wav", - FEEDBACK_SOUND_TOUCH_DIR"/keyasterisk.wav", - FEEDBACK_SOUND_TOUCH_DIR"/keysharp.wav", - /* TOUCH : H/W OR SOFT TOUCH : HOLD(TAP & HOLD) */ - NULL, - /* TOUCH : H/W OR SOFT TOUCH : MULTI TAP */ - NULL, - /* TOUCH : H/W OR SOFT TOUCH : TAP */ - NULL, - /* TOUCH : H/W OR SOFT TOUCH : TAP & HOLD */ - NULL, - - /* NOTIFICATION : INCOMING : MESSAGE */ - NULL, - /* NOTIFICATION : INCOMING : MESSAGE ALERT ON CALL */ - NULL, - /* NOTIFICATION : INCOMING : EMAIL */ - NULL, - /* NOTIFICATION : INCOMING : EMAIL ALERT ON CALL */ - NULL, - /* NOTIFICATION : ALARM : WAKEUP */ - NULL, - /* NOTIFICATION : ALARM : WAKEUP ALERT ON CALL */ - NULL, - /* NOTIFICATION : ALARM : SCHEDULE */ - NULL, - /* NOTIFICATION : ALARM : SCHEDULE ALERT ON CALL */ - NULL, - /* NOTIFICATION : ALARM : TIMER */ - NULL, - /* NOTIFICATION : ALARM : TIMER ALERT ON CALL */ - NULL, - /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) */ - FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", - /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) ALERT ON CALL */ - FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", - - /* OPERATION : POWER ON/OFF */ - FEEDBACK_SOUND_OPER_DIR"/power_on.wav", - NULL, - /* OPERATION : CHARGECONN */ - FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav", - /* OPERATION : CHARGECONN ALERT ON CALL */ - FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav", - /* OPERATION : FULLCHAREGED */ - FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav", - /* OPERATION : FULLCHAREGED ALERT ON CALL */ - FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav", - /* OPERATION : LOW BATTERY */ - FEEDBACK_SOUND_OPER_DIR"/low_battery.wav", - /* OPERATION : LOW BATTERY ALERT ON CALL */ - FEEDBACK_SOUND_OPER_DIR"/low_battery.wav", - /* OPERATION : LOCK/UNLOCK */ - FEEDBACK_SOUND_OPER_DIR"/lock.wav", - FEEDBACK_SOUND_OPER_DIR"/unlock.wav", - /* OPERATION : CALL CONNECT/ DISCONNECT */ - FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", - FEEDBACK_SOUND_OPER_DIR"/call_disconnect.wav", - /* OPERATION : MINUTE MINDER */ - FEEDBACK_SOUND_OPER_DIR"/minute_minder.wav", - /* OPERATION : VIBRATION */ - NULL, - /* OPERATION : CAMERA SHUTTER / SCREEN CAPTURE */ - FEEDBACK_SOUND_OPER_DIR"/shutter.wav", - /* OPERATION : LIST RE-ORDER */ - FEEDBACK_SOUND_OPER_DIR"/list_reorder.wav", - /* OPERATION : LIST SLIDER */ - FEEDBACK_SOUND_OPER_DIR"/slider_sweep.wav", - /* OPERATION : VOLUME KEY */ - FEEDBACK_SOUND_OPER_DIR"/volume_control.wav", -}; - const char* haptic_file[] = { /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : GENERAL */ NULL, diff --git a/include/feedback-internal.h b/include/feedback-internal.h index a6d0160..990cfea 100644 --- a/include/feedback-internal.h +++ b/include/feedback-internal.h @@ -30,6 +30,12 @@ extern "C" { * @brief This file contains the feedback legacy API */ +#define FEEDBACK_DATA_DIR "/opt/usr/share/feedback" +#define FEEDBACK_ORIGIN_DATA_DIR "/usr/share/feedback" + +#define FEEDBACK_RETRY_CNT 1 +#define MAX_FILE_PATH 512 + typedef void* feedback_h; int feedback_init(feedback_h *handle); @@ -39,6 +45,10 @@ int feedback_play_vibration(feedback_h handle, feedback_pattern_e key); int feedback_set_path(feedback_type_e type, feedback_pattern_e key, char* path); int feedback_get_path(feedback_type_e type, feedback_pattern_e key, char* buf, unsigned int buflen); +extern int callstatus; + +feedback_pattern_e feedback_get_alert_on_call_key(feedback_pattern_e pattern); + #ifdef __cplusplus } #endif diff --git a/src/devices.c b/src/devices.c index 8ebd3e1..ac7fbbf 100644 --- a/src/devices.c +++ b/src/devices.c @@ -81,3 +81,14 @@ void devices_exit(void) dev->exit(); } } + +void devices_play(int pattern) +{ + dd_list *elem; + const struct device_ops *dev; + + DD_LIST_FOREACH(dev_head, elem, dev) { + if (dev->play) + dev->play(pattern); + } +} diff --git a/src/feedback-internal.c b/src/feedback-internal.c index f1dbd1b..30f5ee5 100644 --- a/src/feedback-internal.c +++ b/src/feedback-internal.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -48,28 +47,10 @@ typedef struct { xmlDocPtr v_doc; } FEEDBACK_HANDLE; -static int sndstatus; -static int touch_sndstatus; -static int soundon; static int vibstatus; static int vib_level; static int noti_level; -static int callstatus; - -static void feedback_sndstatus_cb(keynode_t *key, void* data) -{ - sndstatus = vconf_keynode_get_bool(key); -} - -static void feedback_touch_sndstatus_cb(keynode_t *key, void* data) -{ - touch_sndstatus = vconf_keynode_get_bool(key); -} - -static void feedback_soundon_cb(keynode_t *key, void* data) -{ - soundon = vconf_keynode_get_int(key); -} +int callstatus; static void feedback_vibstatus_cb(keynode_t *key, void* data) { @@ -86,13 +67,12 @@ static void feedback_noti_cb(keynode_t *key, void* data) noti_level = vconf_keynode_get_int(key); } - static void feedback_callstatus_cb(keynode_t *key, void* data) { callstatus = vconf_keynode_get_int(key); } -static feedback_pattern_e feedback_get_alert_on_call_key(feedback_pattern_e pattern) +feedback_pattern_e feedback_get_alert_on_call_key(feedback_pattern_e pattern) { switch(pattern) { case FEEDBACK_PATTERN_MESSAGE: @@ -120,18 +100,6 @@ static haptic_priority_e feedback_get_priority(feedback_pattern_e pattern) return HAPTIC_PRIORITY_MIDDLE; } -static volume_type_t feedback_get_volume_type(feedback_pattern_e pattern) -{ - if (pattern == FEEDBACK_PATTERN_TAP) - return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_TOUCH; - else if (pattern >= FEEDBACK_PATTERN_KEY0 && pattern <= FEEDBACK_PATTERN_KEY_SHARP) - return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_DIALER; - else if (pattern == FEEDBACK_PATTERN_VOLUME_KEY) - return VOLUME_TYPE_RINGTONE; - - return VOLUME_TYPE_SYSTEM; -} - static int feedback_get_haptic_level(feedback_pattern_e pattern) { int level = -1; @@ -243,9 +211,7 @@ static int feedback_restore_default_file(feedback_type_e type, feedback_pattern_ return FEEDBACK_ERROR_INVALID_PARAMETER; } - if (type == FEEDBACK_TYPE_SOUND) { - cur_path = snd_file[pattern]; - } else { + if (type == FEEDBACK_TYPE_VIBRATION) { cur_path = haptic_file[pattern]; } @@ -275,22 +241,6 @@ int feedback_init(feedback_h *handle) xmlDocPtr v_doc; int ret; - /* Sound Init */ - if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) { - FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) ==> FAIL!!"); - return FEEDBACK_ERROR_OPERATION_FAILED; - } - - if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0) { - FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) ==> FAIL!!"); - return FEEDBACK_ERROR_OPERATION_FAILED; - } - - if (vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) < 0) { - FEEDBACK_ERROR("vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) ==> FAIL!!"); - return FEEDBACK_ERROR_OPERATION_FAILED; - } - /* check vibration status */ if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) < 0) { FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) ==> FAIL!!"); @@ -330,17 +280,11 @@ int feedback_init(feedback_h *handle) } /* add watch for status value */ - vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb, NULL); - vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb, NULL); - vconf_notify_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb, NULL); vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, feedback_vibstatus_cb, NULL); vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb, NULL); vconf_notify_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb, NULL); vconf_notify_key_changed(VCONFKEY_CALL_STATE, feedback_callstatus_cb, NULL); - FEEDBACK_LOG("vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) ==> %d", sndstatus); - FEEDBACK_LOG("vconf_get_bool(VCONFKEY_SETAPPL_....UNDS_BOOL, &touch_sndstatus) ==> %d", touch_sndstatus); - FEEDBACK_LOG("vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) ==> %d", soundon); FEEDBACK_LOG("vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) ==> %d", vibstatus); FEEDBACK_LOG("vconf_get_int(VCONFKEY_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) ==> %d", vib_level); FEEDBACK_LOG("vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) ==> %d", noti_level); @@ -377,9 +321,6 @@ int feedback_fini(feedback_h handle) free(phandle); - vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb); - vconf_ignore_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb); - vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb); vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, feedback_vibstatus_cb); vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb); vconf_ignore_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb); @@ -388,64 +329,6 @@ int feedback_fini(feedback_h handle) return FEEDBACK_ERROR_NONE; } -int feedback_play_sound(feedback_h handle, feedback_pattern_e pattern) -{ - int ret = -1; - int retry = FEEDBACK_RETRY_CNT; - struct stat buf; - - if (!handle) { - FEEDBACK_ERROR("Invalid parameter : handle(NULL)"); - return FEEDBACK_ERROR_INVALID_PARAMETER; - } - - if (sndstatus == 0 && !feedback_get_always_alert_case(pattern)) { - FEEDBACK_LOG("Sound condition is OFF (sndstatus : %d)", sndstatus); - return FEEDBACK_ERROR_NONE; - } - - if (soundon == 1 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) { - FEEDBACK_LOG("Touch feedback sound doesn't work during playing sound"); - return FEEDBACK_ERROR_NONE; - } - - if (touch_sndstatus == 0 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) { - FEEDBACK_LOG("Touch Sound condition is OFF and pattern is touch type (touch_sndstatus : %d, pattern : %s)", touch_sndstatus, str_pattern[pattern]); - return FEEDBACK_ERROR_NONE; - } - - if (callstatus != VCONFKEY_CALL_OFF) { - pattern = feedback_get_alert_on_call_key(pattern); - FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]); - } - - if (snd_file[pattern] == NULL) { - FEEDBACK_LOG("This case(%s) does not play sound", str_pattern[pattern]); - return FEEDBACK_ERROR_NONE; - } - - if (stat(snd_file[pattern], &buf)) { - FEEDBACK_ERROR("%s is not presents", snd_file[pattern]); - ret = feedback_restore_default_file(FEEDBACK_TYPE_SOUND, pattern); - if (FEEDBACK_FAILED(ret)) { - FEEDBACK_ERROR("feedback_restore_default_file(%s) error", str_pattern[pattern]); - return FEEDBACK_ERROR_OPERATION_FAILED; - } - FEEDBACK_LOG("%s is restored", snd_file[pattern]); - } - - do { - ret = mm_sound_play_keysound(snd_file[pattern], feedback_get_volume_type(pattern)); - if (ret == MM_ERROR_NONE) { - FEEDBACK_LOG("Play success! SND filename is %s", snd_file[pattern]); - return FEEDBACK_ERROR_NONE; - } - FEEDBACK_ERROR("mm_sound_play_keysound() returned error(%d)", ret); - } while(retry--); - - return FEEDBACK_ERROR_OPERATION_FAILED; -} - int feedback_play_vibration(feedback_h handle, feedback_pattern_e pattern) { FEEDBACK_HANDLE *phandle = (FEEDBACK_HANDLE *)handle; @@ -523,9 +406,7 @@ int feedback_set_path(feedback_type_e type, feedback_pattern_e pattern, char* pa return FEEDBACK_ERROR_INVALID_PARAMETER; } - if (type == FEEDBACK_TYPE_SOUND) { - cur_path = snd_file[pattern]; - } else { + if (type == FEEDBACK_TYPE_VIBRATION) { cur_path = haptic_file[pattern]; } @@ -563,9 +444,7 @@ int feedback_get_path(feedback_type_e type, feedback_pattern_e pattern, char* bu return FEEDBACK_ERROR_INVALID_PARAMETER; } - if (type == FEEDBACK_TYPE_SOUND) { - cur_path = snd_file[pattern]; - } else { + if (type == FEEDBACK_TYPE_VIBRATION) { cur_path = haptic_file[pattern]; } diff --git a/src/feedback.c b/src/feedback.c index e03c950..95a1d64 100644 --- a/src/feedback.c +++ b/src/feedback.c @@ -21,6 +21,7 @@ #include "feedback.h" #include "feedback-internal.h" #include "feedback-log.h" +#include "devices.h" #define MAX_PATH_LENGTH 256 #define NOT_ASSIGNED NULL @@ -40,6 +41,9 @@ API int feedback_initialize() return FEEDBACK_ERROR_NONE; } + /* initialize device */ + devices_init(); + err = feedback_init(&feedback_handle); if (FEEDBACK_FAILED(err)) { FEEDBACK_ERROR("feedback_init is failed"); @@ -58,6 +62,9 @@ API int feedback_deinitialize() return FEEDBACK_ERROR_NOT_INITIALIZED; } + /* deinitialize device */ + devices_exit(); + err = feedback_fini(feedback_handle); if (FEEDBACK_FAILED(err)) { FEEDBACK_ERROR("feedback_fini is failed"); @@ -87,11 +94,8 @@ API int feedback_play(feedback_pattern_e pattern) return FEEDBACK_ERROR_NONE; } - err = feedback_play_sound(feedback_handle, pattern); - if (FEEDBACK_FAILED(err)) { - FEEDBACK_ERROR("feedback_play_sound is failed"); - return FEEDBACK_ERROR_OPERATION_FAILED; - } + /* play all device */ + devices_play(pattern); err = feedback_play_vibration(feedback_handle, pattern); if (FEEDBACK_FAILED(err)) { @@ -104,6 +108,7 @@ API int feedback_play(feedback_pattern_e pattern) API int feedback_play_type(feedback_type_e type, feedback_pattern_e pattern) { + const struct device_ops *dev; int err = -1; if (feedback_handle == NOT_ASSIGNED) { @@ -128,26 +133,29 @@ API int feedback_play_type(feedback_type_e type, feedback_pattern_e pattern) switch(type) { case FEEDBACK_TYPE_SOUND: - err = feedback_play_sound(feedback_handle, pattern); + dev = find_device(type); + if (dev) { + err = dev->play(pattern); + if (err < 0) + FEEDBACK_ERROR("feedback_play_sound is failed"); + } break; case FEEDBACK_TYPE_VIBRATION: err = feedback_play_vibration(feedback_handle, pattern); + if (FEEDBACK_FAILED(err)) + FEEDBACK_ERROR("feedback_play(type:%d) is failed", type); break; default: FEEDBACK_ERROR("Invalid parameter : type(%d)", type); return FEEDBACK_ERROR_INVALID_PARAMETER; } - if (FEEDBACK_FAILED(err)) { - FEEDBACK_ERROR("feedback_play(type:%d) is failed", type); - return FEEDBACK_ERROR_OPERATION_FAILED; - } - return FEEDBACK_ERROR_NONE; } API int feedback_get_resource_path(feedback_type_e type, feedback_pattern_e pattern, char** path) { + const struct device_ops *dev; int err = -1; char buf[MAX_PATH_LENGTH] = {0,}; @@ -166,19 +174,25 @@ API int feedback_get_resource_path(feedback_type_e type, feedback_pattern_e patt return FEEDBACK_ERROR_INVALID_PARAMETER; } - err = feedback_get_path(type, pattern, buf, MAX_PATH_LENGTH); + if (type == FEEDBACK_TYPE_SOUND) { + dev = find_device(type); + if (dev) + err = dev->get_path(pattern, buf, sizeof(buf)); + } else if (type == FEEDBACK_TYPE_VIBRATION) + err = feedback_get_path(type, pattern, buf, MAX_PATH_LENGTH); + if (FEEDBACK_FAILED(err)) { FEEDBACK_ERROR("feedback_get_path is failed"); return FEEDBACK_ERROR_OPERATION_FAILED; } *path = strdup(buf); - return FEEDBACK_ERROR_NONE; } API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e pattern, char* path) { + const struct device_ops *dev; int err = -1; if (path == NULL) { @@ -196,7 +210,13 @@ API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e patt return FEEDBACK_ERROR_INVALID_PARAMETER; } - err = feedback_set_path(type, pattern, path); + if (type == FEEDBACK_TYPE_SOUND) { + dev = find_device(type); + if (dev) + err = dev->set_path(pattern, path); + } else if (type == FEEDBACK_TYPE_VIBRATION) + err = feedback_set_path(type, pattern, path); + if (FEEDBACK_FAILED(err)) { FEEDBACK_ERROR("feedback_set_path is failed"); return FEEDBACK_ERROR_OPERATION_FAILED; diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..14e5470 --- /dev/null +++ b/src/sound.c @@ -0,0 +1,361 @@ +/* + * libfeedback + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "feedback.h" +#include "feedback-internal.h" +#include "feedback-str.h" +#include "feedback-log.h" +#include "devices.h" + +#define FEEDBACK_SOUND_DIR FEEDBACK_DATA_DIR"/sound" +#define FEEDBACK_SOUND_TOUCH_DIR FEEDBACK_SOUND_DIR"/touch" +#define FEEDBACK_SOUND_OPER_DIR FEEDBACK_SOUND_DIR"/operation" + +static const char* sound_file[] = { + /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : GENERAL */ + FEEDBACK_SOUND_TOUCH_DIR"/touch.wav", + /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : TEXT_NUMERIC_INPUT */ + FEEDBACK_SOUND_TOUCH_DIR"/sip.wav", + FEEDBACK_SOUND_TOUCH_DIR"/sip_backspace.wav", + FEEDBACK_SOUND_TOUCH_DIR"/sip.wav", + /* TOUCH : SCREEN TOUCH : TAP(TOUCH & RELEASE) : DAILER */ + FEEDBACK_SOUND_TOUCH_DIR"/key0.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key1.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key2.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key3.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key4.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key5.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key6.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key7.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key8.wav", + FEEDBACK_SOUND_TOUCH_DIR"/key9.wav", + FEEDBACK_SOUND_TOUCH_DIR"/keyasterisk.wav", + FEEDBACK_SOUND_TOUCH_DIR"/keysharp.wav", + /* TOUCH : H/W OR SOFT TOUCH : HOLD(TAP & HOLD) */ + NULL, + /* TOUCH : H/W OR SOFT TOUCH : MULTI TAP */ + NULL, + /* TOUCH : H/W OR SOFT TOUCH : TAP */ + NULL, + /* TOUCH : H/W OR SOFT TOUCH : TAP & HOLD */ + NULL, + + /* NOTIFICATION : INCOMING : MESSAGE */ + NULL, + /* NOTIFICATION : INCOMING : MESSAGE ALERT ON CALL */ + NULL, + /* NOTIFICATION : INCOMING : EMAIL */ + NULL, + /* NOTIFICATION : INCOMING : EMAIL ALERT ON CALL */ + NULL, + /* NOTIFICATION : ALARM : WAKEUP */ + NULL, + /* NOTIFICATION : ALARM : WAKEUP ALERT ON CALL */ + NULL, + /* NOTIFICATION : ALARM : SCHEDULE */ + NULL, + /* NOTIFICATION : ALARM : SCHEDULE ALERT ON CALL */ + NULL, + /* NOTIFICATION : ALARM : TIMER */ + NULL, + /* NOTIFICATION : ALARM : TIMER ALERT ON CALL */ + NULL, + /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) */ + FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", + /* NOTIFICATION : GENERAL(TICKER/IM/SMS ETC) ALERT ON CALL */ + FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", + + /* OPERATION : POWER ON/OFF */ + FEEDBACK_SOUND_OPER_DIR"/power_on.wav", + NULL, + /* OPERATION : CHARGECONN */ + FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav", + /* OPERATION : CHARGECONN ALERT ON CALL */ + FEEDBACK_SOUND_OPER_DIR"/charger_connection.wav", + /* OPERATION : FULLCHAREGED */ + FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav", + /* OPERATION : FULLCHAREGED ALERT ON CALL */ + FEEDBACK_SOUND_OPER_DIR"/fully_charged.wav", + /* OPERATION : LOW BATTERY */ + FEEDBACK_SOUND_OPER_DIR"/low_battery.wav", + /* OPERATION : LOW BATTERY ALERT ON CALL */ + FEEDBACK_SOUND_OPER_DIR"/low_battery.wav", + /* OPERATION : LOCK/UNLOCK */ + FEEDBACK_SOUND_OPER_DIR"/lock.wav", + FEEDBACK_SOUND_OPER_DIR"/unlock.wav", + /* OPERATION : CALL CONNECT/ DISCONNECT */ + FEEDBACK_SOUND_OPER_DIR"/call_connect.wav", + FEEDBACK_SOUND_OPER_DIR"/call_disconnect.wav", + /* OPERATION : MINUTE MINDER */ + FEEDBACK_SOUND_OPER_DIR"/minute_minder.wav", + /* OPERATION : VIBRATION */ + NULL, + /* OPERATION : CAMERA SHUTTER / SCREEN CAPTURE */ + FEEDBACK_SOUND_OPER_DIR"/shutter.wav", + /* OPERATION : LIST RE-ORDER */ + FEEDBACK_SOUND_OPER_DIR"/list_reorder.wav", + /* OPERATION : LIST SLIDER */ + FEEDBACK_SOUND_OPER_DIR"/slider_sweep.wav", + /* OPERATION : VOLUME KEY */ + FEEDBACK_SOUND_OPER_DIR"/volume_control.wav", +}; + +static int sndstatus; +static int touch_sndstatus; +static int soundon; + +static void feedback_sndstatus_cb(keynode_t *key, void* data) +{ + sndstatus = vconf_keynode_get_bool(key); +} + +static void feedback_touch_sndstatus_cb(keynode_t *key, void* data) +{ + touch_sndstatus = vconf_keynode_get_bool(key); +} + +static void feedback_soundon_cb(keynode_t *key, void* data) +{ + soundon = vconf_keynode_get_int(key); +} + +static volume_type_t get_volume_type(feedback_pattern_e pattern) +{ + if (pattern == FEEDBACK_PATTERN_TAP) + return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_TOUCH; + else if (pattern >= FEEDBACK_PATTERN_KEY0 && pattern <= FEEDBACK_PATTERN_KEY_SHARP) + return VOLUME_TYPE_SYSTEM|VOLUME_GAIN_DIALER; + else if (pattern == FEEDBACK_PATTERN_VOLUME_KEY) + return VOLUME_TYPE_RINGTONE; + + return VOLUME_TYPE_SYSTEM; +} + +static bool get_always_alert_case(feedback_pattern_e pattern) +{ + switch (pattern) { + case FEEDBACK_PATTERN_WAKEUP: + case FEEDBACK_PATTERN_WAKEUP_ON_CALL: + return true; + default: + break; + } + return false; +} + +static int change_symlink(const char *sym_path, const char *new_path) +{ + struct stat buf; + + assert(sym_path != NULL && strlen(sym_path)); + assert(new_path != NULL && strlen(new_path)); + + /* check symbolic link file existence */ + if (stat(sym_path, &buf)) { + FEEDBACK_ERROR("file(%s) is not presents", sym_path); + return -EPERM; + } + + if (unlink(sym_path) < 0) + FEEDBACK_LOG("unlink(%s) : %s", sym_path, strerror(errno)); + + if (symlink(new_path, sym_path) < 0) { + FEEDBACK_ERROR("symlink(%s) : %s", sym_path, strerror(errno)); + return -EPERM; + } + + return 0; +} + +static int restore_default_file(feedback_pattern_e pattern) +{ + char default_path[PATH_MAX] = {0,}; + const char *cur_path; + char *temp; + int ret; + + cur_path = sound_file[pattern]; + /* if there isn't cur_path, it already returns before calling this api */ + if (cur_path == NULL || strlen(cur_path) == 0) { + FEEDBACK_ERROR("Invalid parameter : cur_path(NULL)"); + return -EPERM; + } + + temp = strcat(default_path, FEEDBACK_ORIGIN_DATA_DIR); + strcat(temp, cur_path+strlen(FEEDBACK_DATA_DIR)); + FEEDBACK_LOG("default_path : %s", default_path); + + ret = change_symlink(cur_path, default_path); + if (ret < 0) { + FEEDBACK_ERROR("change_symlink is failed"); + return -EPERM; + } + + return 0; +} + +static void sound_init(void) +{ + /* Sound Init */ + if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) < 0) + FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sndstatus) ==> FAIL!!"); + + if (vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) < 0) + FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, &touch_sndstatus) ==> FAIL!!"); + + if (vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) < 0) + FEEDBACK_ERROR("vconf_get_int(VCONFKEY_SOUND_STATUS, &soundon) ==> FAIL!!"); + + /* add watch for status value */ + vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb, NULL); + vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb, NULL); + vconf_notify_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb, NULL); +} + +static void sound_exit(void) +{ + /* remove watch */ + vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, feedback_sndstatus_cb); + vconf_ignore_key_changed(VCONFKEY_SOUND_STATUS, feedback_soundon_cb); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_SOUNDS_BOOL, feedback_touch_sndstatus_cb); +} + +static int sound_play(feedback_pattern_e pattern) +{ + struct stat buf; + int retry = FEEDBACK_RETRY_CNT, ret; + + if (sndstatus == 0 && !get_always_alert_case(pattern)) { + FEEDBACK_LOG("Sound condition is OFF (sndstatus : %d)", sndstatus); + return 0; + } + + if (soundon == 1 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) { + FEEDBACK_LOG("Touch feedback sound doesn't work during playing sound"); + return 0; + } + + if (touch_sndstatus == 0 && pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD) { + FEEDBACK_LOG("Touch Sound condition is OFF and pattern is touch type (touch_sndstatus : %d, pattern : %s)", touch_sndstatus, str_pattern[pattern]); + return 0; + } + + if (callstatus != VCONFKEY_CALL_OFF) { + pattern = feedback_get_alert_on_call_key(pattern); + FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]); + } + + if (sound_file[pattern] == NULL) { + FEEDBACK_LOG("This case(%s) does not play sound", str_pattern[pattern]); + return 0; + } + + if (stat(sound_file[pattern], &buf)) { + FEEDBACK_ERROR("%s is not presents", sound_file[pattern]); + ret = restore_default_file(pattern); + if (ret < 0) { + FEEDBACK_ERROR("restore_default_file(%s) error", str_pattern[pattern]); + return -EPERM; + } + FEEDBACK_LOG("%s is restored", sound_file[pattern]); + } + + do { + ret = mm_sound_play_keysound(sound_file[pattern], get_volume_type(pattern)); + if (ret == MM_ERROR_NONE) { + FEEDBACK_LOG("Play success! SND filename is %s", sound_file[pattern]); + return 0; + } + FEEDBACK_ERROR("mm_sound_play_keysound() returned error(%d)", ret); + } while(retry--); + + return -EPERM; +} + +static int sound_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen) +{ + const char *cur_path; + int retry = FEEDBACK_RETRY_CNT; + + assert(buf != NULL && buflen > 0); + + cur_path = sound_file[pattern]; + if (cur_path == NULL) { + FEEDBACK_ERROR("This pattern(%s) in sound type is not supported to play", str_pattern[pattern]); + snprintf(buf, buflen, "NULL"); + return -ENOENT; + } + + do { + if(readlink(cur_path, buf, buflen) < 0) { + FEEDBACK_ERROR("readlink is failed : %s", strerror(errno)); + return -EPERM; + } + } while(retry--); + + return 0; +} + +static int sound_set_path(feedback_pattern_e pattern, char *path) +{ + const char *cur_path; + int ret; + + assert(path != NULL); + + if (access(path, F_OK) != 0) { + FEEDBACK_ERROR("Invalid parameter : path does not exist"); + return -ENOENT; + } + + cur_path = sound_file[pattern]; + if (cur_path == NULL) { + FEEDBACK_ERROR("This pattern(%s) in sound type is not supported to play", str_pattern[pattern]); + return -ENOENT; + } + + ret = change_symlink(cur_path, path); + if (ret < 0) { + FEEDBACK_ERROR("change_symlink is failed"); + return -EPERM; + } + + return 0; +} + +static const struct device_ops sound_device_ops = { + .type = FEEDBACK_TYPE_SOUND, + .init = sound_init, + .exit = sound_exit, + .play = sound_play, + .get_path = sound_get_path, + .set_path = sound_set_path, +}; + +DEVICE_OPS_REGISTER(&sound_device_ops); -- 2.7.4