seperate sound device from feedback internal code 09/10409/3
authorjy910.yun <jy910.yun@samsung.com>
Tue, 1 Oct 2013 13:58:43 +0000 (22:58 +0900)
committerjy910.yun <jy910.yun@samsung.com>
Tue, 1 Oct 2013 15:19:23 +0000 (00:19 +0900)
Change-Id: I396351854963b08f23de5bb468b9430a8cc62e54
Signed-off-by: jy910.yun <jy910.yun@samsung.com>
CMakeLists.txt
include/devices.h
include/feedback-file.h
include/feedback-internal.h
src/devices.c
src/feedback-internal.c
src/feedback.c
src/sound.c [new file with mode: 0644]

index 3e7ff51..1fa250a 100644 (file)
@@ -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)
index 7439065..226c910 100644 (file)
@@ -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)  \
index 435be83..f7ab443 100644 (file)
 #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"
 #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,
index a6d0160..990cfea 100644 (file)
@@ -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
index 8ebd3e1..ac7fbbf 100644 (file)
@@ -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);
+       }
+}
index f1dbd1b..30f5ee5 100644 (file)
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <mm_sound_private.h>
 #include <vconf.h>
 #include <haptic.h>
 #include <fcntl.h>
@@ -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, &noti_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];
        }
 
index e03c950..95a1d64 100644 (file)
@@ -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 (file)
index 0000000..14e5470
--- /dev/null
@@ -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 <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <vconf.h>
+#include <mm_sound_private.h>
+
+#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);